I want to pass configuration parameters from docker-compose file to my Symfony application, I tried this:
app:
image: <NGINX + PHP-FPM IMAGE>
environment:
DATABASE_HOST: db
My parameters.yml file :
database_host: "%env(DATABASE_HOST)%"
I get error 500 "Environment variable not found: DATABASE_HOST"
I also tried SYMFONY__DATABASE_HOST in docker-compose but also not working.
How does it work?
The error you're receiving refers to Symfony runtime environment variables (see here). Docker compose environment variables are retrieved from the .env file that resides within the build context (AKA the directory where you want docker-compose to run from) of the docker-compose.yml file. What you really want to do is make sure that the environment variables you set in your Symfony config/parameters and your docker-compose.yml file match, especially the db host.
You should consider breaking your image up into PHP-FPM and Nginx images to have better potential scalability and a separation of concerns according to the best practices outlined by Docker here. All of these technologies have regularly-maintained images available on Docker Hub.
Here's my docker-compose.yml that creates containers for PHP-FPM, MySQL, and Nginx in a multicontainer environment with the latest stable packages available as of today.
version: '3'
services:
db:
image: mysql
volumes:
- ./.data/db:/var/lib/mysql
environment:
MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
MYSQL_DATABASE: ${MYSQL_DATABASE}
MYSQL_USER: ${MYSQL_USER}
MYSQL_PASSWORD: ${MYSQL_PASSWORD}
php:
build: php7.1-fpm
depends_on:
- db
ports:
- "9000:9000"
volumes:
- symfony-bind-mount:/var/www/symfony
- symfony-logs-bind-mount:/var/www/symfony/app/logs
nginx:
build: nginx
depends_on:
- php
ports:
- "8025:8025"
- "80:80"
volumes:
- symfony-bind-mount:/var/www/symfony
- nginx-logs-bind-mount:/var/log/nginx
volumes:
symfony-bind-mount:
driver: local
driver_opts:
o: bind,rw
type: none
device: ${SYMFONY_APP_PATH}
nginx-logs-bind-mount:
driver: local
driver_opts:
o: bind,rw
type: none
device: ${DOCKER_SYMFONY_PATH}/logs/nginx
symfony-logs-bind-mount:
driver: local
driver_opts:
o: bind,rw
type: none
device: ${DOCKER_SYMFONY_PATH}/logs/symfony
Here's my .env file:
# Symfony application's path
SYMFONY_APP_PATH=/absolute/path/to/symfony/project
# Path to local docker-symfony repository
DOCKER_SYMFONY_PATH=/absolute/path/to/sibling/docker/directory
# MySQL
MYSQL_ROOT_PASSWORD=root
MYSQL_DATABASE=mydb
MYSQL_USER=
MYSQL_PASSWORD=password
You can checkout my fork of maxpou's docker-symfony repository here. I've updated the docker-compose.yml and the bind mounts to be compatible with version 3 of the Compose file format.
Related
when I try to create a local WordPress development environment using docker, it throws an error
(root) Additional property MySQL is not allowed
Docker compose file
web:
image: wordpress
links:
- mysql
environment:
- WORDPRESS_DB_PASSWORD=password
ports:
- "127.0.0.3:8080:80"
mysql:
image: mysql:5.7
environment:
- MYSQL_ROOT_PASSWORD=password
- MYSQL_DATABASE=my-wpdb
command i used : Docker compose up -d
It looks like you've found a very very old example using the "version 1" Compose format. For a long time, the Docker Compose tool interpreted files without a version: line as being in this format, but more recently the tool has changed to interpret these lines as being in a much newer, and somewhat incompatible, "Compose Specification" format.
I'd recommend using either version 2 or version 3 of the Compose file format (version 2 has some resource-constraint options for non-Swarm hosts that are often useful). In spite of the Docker documentation claiming they're "legacy", every version of Compose from the past several years supports these.
For the file you show, the required changes are straightforward:
Indent the entire file one step, and add an unindented services: line above the existing content.
Above that, add another line version: '3.8' (or '2.4').
Delete the obsolete links: block; Compose provides network setup for you so this isn't required.
version: '3.8'
services:
web:
image: wordpress
environment:
- WORDPRESS_DB_PASSWORD=password
ports:
- "127.0.0.3:8080:80"
mysql:
image: mysql:5.7
environment:
- MYSQL_ROOT_PASSWORD=password
- MYSQL_DATABASE=my-wpdb
The newer file format has support for declaring named volumes in the Compose file itself, which would let you declare storage for the database, and #ioeshu's extended example includes the relevant volumes: blocks.
This yaml code works fine
services:
db:
# We use a mariadb image which supports both amd64 & arm64 architecture
image: mariadb:10.6.4-focal
# If you really want to use MySQL, uncomment the following line
#image: mysql:8.0.27
command: '--default-authentication-plugin=mysql_native_password'
volumes:
- db_data:/var/lib/mysql
restart: always
environment:
- MYSQL_ROOT_PASSWORD=somewordpress
- MYSQL_DATABASE=wordpress
- MYSQL_USER=wordpress
- MYSQL_PASSWORD=wordpress
expose:
- 3306
- 33060
wordpress:
image: wordpress:latest
volumes:
- wp_data:/var/www/html
ports:
- 80:80
restart: always
environment:
- WORDPRESS_DB_HOST=db
- WORDPRESS_DB_USER=wordpress
- WORDPRESS_DB_PASSWORD=wordpress
- WORDPRESS_DB_NAME=wordpress
volumes:
db_data:
wp_data:
Here is my docker-compose.yml file:
version: '3.9'
services:
db:
image: mysql:5.7
restart: always
command: [
'--disable-partition-engine-check',
'--default_authentication_plugin=mysql_native_password',
'--character-set-server=utf8mb4',
'--collation-server=utf8mb4_unicode_ci',
'--max_allowed_packet=100M'
]
volumes:
- ./db_data:/var/lib/mysql
environment:
MYSQL_DATABASE: wordpress
MYSQL_ROOT_PASSWORD: pswd4!
pma:
image: phpmyadmin/phpmyadmin
environment:
PMA_HOST: db
PMA_PORT: 3306
MYSQL_ROOT_PASSWORD: pswd4!
UPLOAD_LIMIT: 1G
ports:
- 8080:80
depends_on:
- db
wp:
image: wordpress:php8.0
ports:
- 80:80
volumes:
- ./config/php.conf.ini:/usr/local/etc/php/conf.d/conf.ini
- ./:/var/www/html
environment:
WORDPRESS_DB_HOST: db
WORDPRESS_DB_NAME: wordpress
WORDPRESS_DB_USER: root
WORDPRESS_DB_PASSWORD: pswd4!
WORDPRESS_DEBUG: 1
depends_on:
- db
links:
- db:mysql
hostname: test.localhost
wpcli:
image: wordpress:cli-php8.0
volumes_from:
- wp
depends_on:
- db
- wp
links:
- db:mysql
entrypoint: wp
command: "--info"
volumes:
db_data:
When I try to use wp-cli in Docker (e.g. docker-compose run --rm wpcli plugin list), it gets an error that it cannot connect to the database:
Error: `Access denied for user 'username_here'#'192.168.32.5' (using password: YES)`
Error establishing a database connection
This either means that the username and password information in your `wp-config.php` file is incorrect or we can’t contact the database server at `mysql`. This could mean your host’s database server is down.
Are you sure you have the correct username and password?
Are you sure you have typed the correct hostname?
Are you sure the database server is running?
If you’re unsure what these terms mean you should probably contact your host. If you still need help you can always visit the WordPress Support Forums. `Access denied for user 'username_here'#'192.168.32.5' (using password: YES)
`
It looks like wp-cli is seeing bad database credentials (username_here instead of root)
Result of executing docker-compose run --rm wpcli config list command:
What could be wrong? I've searched all over the internet, lost several hours and still haven't found the cause of the problem.
You should specify the same set of environment variables as in your wp container for your wpcli container. If not, default variables from a php file in wordpress are used.
Do be careful : volumes_from and link options are deprecated in compose v3. For the link option, docker-compose creates a network automatically (or you can specify one if you prefer) and the embed docker dns automatically attributes aliases to your containers based on their names (or in compose the service name). More info on that here
For volumes, you can find more info here
I'm having an issue with my php container not connecting to my database container.
My docker-compose.yml :
version: "2"
volumes:
# this is the mysql data volume we are going to host the data inside
dev_mysql_data:
# This volume is used for elasticsearch
dev_elastic_search:
networks:
mp_pixel:
driver: bridge
ipam:
driver: default
config:
- subnet: 172.20.0.0/16
services:
# database container for local development purposes
dev_database:
image: mysql:5.6
networks:
mp_pixel:
aliases:
- database
ports:
# port 3304 (external) is for use on your desktop sql client
# port 3306 (internal) is for use inside your application code
- 3304:3306
volumes:
# mount the mysql_data docker volume to host the local development database
- dev_mysql_data:/var/lib/mysql
# the provision file helps when trying to use the provision script to clone databases
- ./provision.cnf:/provision.cnf
environment:
MYSQL_ROOT_PASSWORD: pixel
# This is the local development version of the nginx container
dev_nginx:
image: mp-pixel-nginx:latest
build: ./nginx
ports:
- '80:80'
- '443:443'
networks:
mp_pixel:
aliases:
- nginx
depends_on:
- dev_phpfpm
volumes_from:
- dev_phpfpm
environment:
- VIRTUAL_HOST=~^(mp-pixel|mp-location|mp-feedback|mp-user|mp-phone|mp-loancalculator|mp-seo|mp-media|mp-listing|mp-development|mp-kpi|mp-newsletter|mp-auth|mp-worker|mp-search)-ph-dev.pixel.local
# This is the local development version of the phpfpm container
dev_phpfpm:
image: mp-pixel-phpfpm:latest
build:
context: ./
args:
# this build might fail, if so, run in a terminal: export SSH_KEY=$(cat ~/.ssh/id_rsa)
- SSH_KEY=$SSH_KEY
networks:
mp_pixel:
aliases:
- phpfpm
depends_on:
- dev_database
volumes:
# we override the images /www directory with the code from the live machine
- ./:/www
env_file:
# inside this file, are the shared database secrets such as username/password
- ./env/common
- ./env/dev
dev_elasticsearch:
image: docker.elastic.co/elasticsearch/elasticsearch:5.3.3
networks:
mp_pixel:
aliases:
- elasticsearch
ulimits:
memlock:
soft: -1
hard: -1
nofile:
soft: 65536
hard: 65536
mem_limit: 1g
cap_add:
- IPC_LOCK
volumes:
- dev_elastic_search:/usr/share/elasticsearch/data
ports:
- 9200:9200
environment:
- cluster.name=dev-elasticsearch-pixel
- bootstrap.memory_lock=true
- "ES_JAVA_OPTS=-Xms512m -Xmx512m"
- "xpack.security.enabled=false"
I run it with docker-compose up and the php logs show
An exception occured in driver: SQLSTATE[HY000] [2002] Connection timed out
I try to access the database container with docker exec, and I can confirm that I have the right credentials.
What could be the problem?
When your containers are up, did you already try to connect to the database with a tool like Sequel Pro? Maybe the database is just not initialized and because of this, the connection from the php container can't be established? You tried to access the db container but not the database itself.
Additionally you could add some more environment variables to the database section of your docker-compose.yml
environment:
- MYSQL_ALLOW_EMPTY_PASSWORD=yes
- MYSQL_DATABASE=databasename
- MYSQL_USER=databaseuser
- MYSQL_PASSWORD=databasepassword
Hope that helps
I have all set in my local machine for virtual machine shared folders. I have following code in my Docker compose file for Wordpress service. but not sure how the volumes work here. Can you please explain?
version: '2'
services:
database:
image: mysql:5.6
volumes:
- ./mysql-data:/var/lib/mysql
environment:
MYSQL_ROOT_PASSWORD: password
restart: unless-stopped
wordpress:
image: wordpress:4.9.6
ports:
- 49160:80
links:
- database:mysql
volumes:
- ./wordpress:/var/www/html/wp-content
environment:
WORDPRESS_DB_PASSWORD: password
restart: unless-stopped
phpmyadmin:
image: phpmyadmin/phpmyadmin
links:
- database:db
ports:
- 8080:80
Does the above volumes line of code mean, does it need to create a WordPress folder in my docker-compsose.yml file that I am currently running?
Or is it anyhow related to my shared folders in virtual machine?
Basically volumes are instruments for Docker so it can retain data. Docker containers are generally designed to be stateless, but if you need to retain state/information between runs, that's where volumes come in.
You can create an unnamed volume in the following way:
volumes:
- /var/www/html/wp-content
This will retain your wp-content folder in the internal volumes storage without a particular name.
A second way would be to give it a name, making it a named volume:
volumes:
- mywp:/var/www/html/wp-content
And the final type, which is also what you are doing, is called a Volume Bind. This basically binds/mounts the content of a folder on your host machine in the container. So if you change a file in either place, it will be saved on the other.
volumes:
- ./wordpress:/var/www/html/wp-content
In order to use your Volume Bind, you will need to create the folder "wordpress" in the folder where you're running the docker-compose.yaml (usually your root folder). Afterwards, when your installation changes within the container, it will also change on the bind and vice-versa.
EDIT: In your particular case the following should work:
version: '3.2'
services:
database:
image: mysql:5.6
volumes:
- ./mysql-data:/var/lib/mysql
environment:
MYSQL_ROOT_PASSWORD: password
restart: unless-stopped
wordpress:
image: wordpress:4.9.6
ports:
- 49160:80
links:
- database:mysql
volumes:
- type: bind
source: ./wordpress
target: /var/www/html/wp-content
environment:
WORDPRESS_DB_PASSWORD: password
restart: unless-stopped
phpmyadmin:
image: phpmyadmin/phpmyadmin
links:
- database:db
ports:
- 8080:80
Adding a volume to your docker-compose.yml file will enable you to 'mount' content from your local file system into the running container.
So, about the following line here:
volumes:
- ./wordpress:/var/www/html/wp-content
This means that whatever's in your local wordpress directory will be placed in the /var/www/html/wp-content directory inside your container. This is useful because it allows you to develop themes and plugins locally and automatically inject them into the running container.
To avoid confusion, I'd recommend renaming wordpress to something else, so it's clear that you're mounting only your WordPress content, and not core files themselves.
I have a similar setup here, in case you need another reference:
https://github.com/alexmacarthur/wp-skateboard
Description
I am trying to build an equal configuration in my local docker-environment like on our production system. After spending some time investigating and rebuilding the docker container setup, still can't get it to work and Graylog is not receiving any data.
Overview and interim results
web, php and db container are in use for the symfony based application
symfony runs properly on localhost in php-container and generates logfiles
symfony-logfiles are located here: /var/www/html/var/logs/*.log
symfony-logfiles format is json / gelf
all other containers are also up and running when starting the complete composition
filebeat configuration is based on first link below
filebeat.yml seems to retrieve any logfile found in any container
filebeat configured to transfer data directly to elasticsearch
elasticsearch persists data in mongodb
all graylog related data in persisted in named volumes in docker
additionally I am working with docker-sync on a Mac
The docker-compose.yml is based on the following resources:
https://github.com/jochenchrist/docker-logging-elasticsearch
http://docs.graylog.org/en/2.4/pages/installation/docker.html?highlight=docker
https://www.elastic.co/guide/en/beats/filebeat/6.3/running-on-docker.html
https://www.elastic.co/guide/en/beats/filebeat/6.3/filebeat-reference-yml.html
config.yml
# Monolog Configuration
monolog:
channels: [graylog]
handlers:
graylog:
type: stream
formatter: line_formatter
path: "%kernel.logs_dir%/graylog.log"
channels: [graylog]
docker-compose.yml
version: "3"
services:
web:
image: nginx
ports:
- "80:80"
- "443:443"
links:
- php
volumes:
- ./docker-config/nginx.conf:/etc/nginx/conf.d/default.conf
- project-app-sync:/var/www/html
- ./docker-config/localhost.crt:/etc/nginx/ssl/localhost.crt
- ./docker-config/localhost.key:/etc/nginx/ssl/localhost.key
php:
build:
context: .
dockerfile: ./docker-config/Dockerfile-php
links:
- graylog
volumes:
- project-app-sync:/var/www/html
- ./docker-config/php.ini:/usr/local/etc/php/php.ini
- ./docker-config/www.conf:/usr/local/etc/php-fpm.d/www.conf
db:
image: mysql
ports:
- "3306:3306"
environment:
- MYSQL_ALLOW_EMPTY_PASSWORD=yes
- MYSQL_DATABASE=project
- MYSQL_USER=project
- MYSQL_PASSWORD=password
volumes:
- ./docker-config/mysql.cnf:/etc/mysql/conf.d/mysql.cnf
- project-mysql-sync:/var/lib/mysql
# Graylog / Filebeat
filebeat:
build: ./docker-config/filebeat
volumes:
- /var/lib/docker/containers:/var/lib/docker/containers:ro
- /var/run/docker.sock:/var/run/docker.sock
networks:
- graylog-network
depends_on:
- graylog-elasticsearch
graylog:
image: graylog/graylog:2.4
volumes:
- graylog-journal:/usr/share/graylog/data/journal
networks:
- graylog-network
environment:
- GRAYLOG_PASSWORD_SECRET=somepasswordpepper
- GRAYLOG_ROOT_PASSWORD_SHA2=8c6976e5b5410415bde908bd4dee15dfb167a9c873fc4bb8a81f6f2ab448a918
- GRAYLOG_WEB_ENDPOINT_URI=http://127.0.0.1:9000/api
links:
- graylog-mongo:mongo
- graylog-elasticsearch:elasticsearch
depends_on:
- graylog-mongo
- graylog-elasticsearch
ports:
# Graylog web interface and REST API
- 9000:9000
graylog-mongo:
image: mongo:3
volumes:
- graylog-mongo-data:/data/db
networks:
- graylog-network
graylog-elasticsearch:
image: docker.elastic.co/elasticsearch/elasticsearch:5.6.10
ports:
- "9200:9200"
volumes:
- graylog-elasticsearch-data:/usr/share/elasticsearch/data
networks:
- graylog-network
environment:
- cluster.name=graylog
- "discovery.zen.minimum_master_nodes=1"
- "discovery.type=single-node"
- http.host=0.0.0.0
- transport.host=localhost
- network.host=0.0.0.0
# Disable X-Pack security: https://www.elastic.co/guide/en/elasticsearch/reference/5.6/security-settings.html#general-security-settings
- xpack.security.enabled=false
- "ES_JAVA_OPTS=-Xms512m -Xmx512m"
ulimits:
memlock:
soft: -1
hard: -1
volumes:
project-app-sync:
external: true
project-mysql-sync: ~
graylog-mongo-data:
driver: local
graylog-elasticsearch-data:
driver: local
graylog-journal:
driver: local
networks:
graylog-network: ~
Dockerfile of filebeat container
FROM docker.elastic.co/beats/filebeat:6.3.1
COPY filebeat.yml /usr/share/filebeat/filebeat.yml
# must run as root to access /var/lib/docker and /var/run/docker.sock
USER root
RUN chown root /usr/share/filebeat/filebeat.yml
# dont run with -e, to disable output to stderr
CMD [""]
filebeat.yml
filebeat.prospectors:
- type: docker
paths:
- '/var/lib/docker/containers/*/*.log'
# path to symfony based logs
- '/var/www/html/var/logs/*.log'
containers.ids: '*'
processors:
- decode_json_fields:
fields: ["host","application","short_message"]
target: ""
overwrite_keys: true
- add_docker_metadata: ~
output.elasticsearch:
# transfer data to elasticsearch container?
hosts: ["localhost:9200"]
logging.to_files: true
logging.to_syslog: false
Graylog backend
After setting up this docker composition I started the Graylog web-view and set up a collector and input as described here:
http://docs.graylog.org/en/2.4/pages/collector_sidecar.html#step-by-step-guide
Maybe I have totally misunderstood how this could work. I am not totally sure if Beats from Elastic is the same as the filebeats container and if the sidecar collector is something extra I forgot to add. Maybe I misconfigured the collector and input in graylog?!
I would be thankful to any help or working example according to my problem ...
Graylog seems to be running on http://127.0.0.1:9000/api which is in the container. You might want to run it as http://graylog:9000/api or as http://0.0.0.0:9000/api
Accessing the other images from within any of the other images will have be done with the same name as the service name, as defined in the docker-compose.yml files. The url to the graylog-elasticsearch would be something like: http://graylog-elasticsearch/.... if you would post to localhost it would stay inside its own image.
Hope this will help you along in finding the solution.