Symfony app deployment with docker - symfony

I come here because I develop an app with Symfony3. And I've some questions about the deployment of the app.
Actually I use docker-compose:
version: '2'
services:
nginx:
build: ./docker/nginx/
ports:
- 8081:80
volumes:
- .:/home/docker:ro
- ./docker/nginx/default.conf:/etc/nginx/conf.d/default.conf:ro
- ./docker/nginx/nginx.conf:/etc/nginx/nginx.conf:ro
networks:
- default
php:
build: ./docker/php/
volumes:
- .:/home/docker:rw
- ./docker/php/php.ini:/usr/local/etc/php/conf.d/custom.ini:ro
working_dir: /home/docker
networks:
- default
dns_search:
- php
db:
image: mariadb:latest
ports:
- 3307:3306
environment:
- MYSQL_ROOT_PASSWORD=collectionManager
- MYSQL_USER=collectionManager
- MYSQL_PASSWORD=collectionManager
- MYSQL_DATABASE=collectionManager
volumes:
- mariadb_data:/var/lib/mysql
networks:
- default
dns_search:
- db
search:
build: ./docker/search/
ports:
- 9200:9200
- 9300:9300
volumes:
- elasticsearch_data:/usr/share/elasticsearch/data
networks:
- default
dns_search:
- search
volumes:
mariadb_data:
driver: local
elasticsearch_data:
driver: local
networks:
default:
nginx is clear, engine is PHP-FPM with some extensions and composer, db is MariaDB, and search ElasticSearch with some plugins.
Before I don't use Docker and to deploy I used Megallanes or Deployer, when I want to deploy webapp.
With Docker I can use the docker-compose file and recreate images and container on the server, I also can save my containers in images and in tar archive and load it on the server. It's okay for nginx, and php-fpm, but what about elasticsearch and the db ? Because I need to keep data in for future update of the code. Then when I deploy the code I need to execute a Doctrine Migration and maybe some commands, and Deployer do it perfectly with some other interresting things. And how I deploy the code with Docker ? Can we use both ? Deployer for code and Docker for services ?
Thanks a lot for your help.

First of all , Please try using user-defined networks, they have additional features vs legacy linking like Embedded DNS. Meaning you can call other containers on the same network with their names in your applications. Containers on a User defined network are isolate from containers on another User defined network.
To create a user defined network:
docker network create --driver bridge <networkname>
Dockerfile to use user defined network example:
search:
restart: unless-stopped
build: ./docker/search/
ports:
- "9200:9200"
- "9300:9300"
networks:
- <networkname>
Second: I noticed you didnt use data volumes for you DB and ElasticSearch.
You need to mount volumes at certain points to keep your persistant data.
Third: When you export your containers it wont contain mounted volumes. You need to back up volume data and migrate it manually.
To backup volume data:
docker run --rm --volumes-from db -v $(pwd):/backup ubuntu tar cvf /backup/backup.tar /dbdata
The above command will create a container, mounts volumes from DB container and mounts current directory in container as /backup , uses ubuntu image and tar command to create a backup of /dbdata in container (consider changing this to your dbdirectory) in the /backup that is mounted from your docker hosts). after the operation completes the transient container will be removed (ubuntu container we used for creating the backup with --rm switch).
To restore:
You copy the tar archive to the remote location and create your container with empty mounted volume. then extract the tar archive in that volume using the following command.
docker run --rm --volumes-from dbstore2 -v $(pwd):/backup ubuntu bash -c "cd /dbdata && tar xvf /backup/backup.tar --strip 1"

Related

Multiple docker-compose: Error: getaddrinfo EAI_AGAIN from frontend to backend

I have 2 folders separated, one for backend and one for frontend services:
backend/docker-compose.yml
frontend/docker-compose.yml
The backend has a headless wordpress installation on nginx, with the scope to serve the frontend as an api service. The frontend runs on next.js. Here are the 2 different docker-compose.yml:
backend/docker-compose.yml
version: '3.9'
services:
nginx:
image: nginx:latest
container_name: my-app-nginx
ports:
- '80:80'
- '443:443'
- '8080:8080'
...
networks:
- internal-network
mysql:
...
networks:
- internal-network
wordpress:
...
networks:
- internal-network
networks:
internal-network:
external: true
frontend/docker-compose.yml
version: '3.9'
services:
nextjs:
build:
...
container_name: my-app-nextjs
restart: always
ports:
- 3000:3000
networks:
- internal-network
networks:
internal-network:
driver: bridge
name: internal-network
In the frontend I use the fetch api in nextjs as following:
fetch('http://my-app-nginx/wp-json/v1/enpoint', ...)
I tried also with ports 80 and 8080, without success.
The sequence of commands I run are:
docker network create internal-network
in backend/ folder, docker-compose up -d (all backend containers run fine, I can fetch data with Postman from WordPress api)
in frontend/ folder, docker-compose up -d fails with the error Error: getaddrinfo EAI_AGAIN my-app-nginx
I am not a very expert user of docker so I might miss something here, but I understand that there might be internal network issues over the containers. I read many answers regarding this topic but I couldn't figure it out.
Any recommendations?
Just to add a proper answer:
Generally you should NOT really want to be executing multiple docker-compose up -d commands
If you want to combine two separate docker-compose configs and run as one (slightly more preferable), you can use the extends keyword as described in the docs
However, I would suggest that you treat it as a single docker-compose project which can itself have multiple nested git repositories:
Example SO answer - Git repository setup for a Docker application consisting of multiple repositories
You can keep your code in a mono-repo or multiple repos, up to you
Real working example to backup using your applications that validates this approach:
headless-wordpress-nextjs-starter-kit and it's docker-compose.yml
I have found this thread here
Communication between multiple docker-compose projects
By looking at the most upvoted answers, I wonder if it is related to network prefix?
It seems like the internal-network would be prefixed with frontend_? On the other hand you can also try to locate the network by name in backend/docker-compose.yml:
networks:
internal-network:
external:
name: internal-network
The issue is external networks need the network name specified (because docker compose prefixes resources by default). Your backend docker compose network section should look like this:
networks:
internal-network:
name: internal-network
external: true
You are creating the network in your frontend docker compose so you should omit the docker network create ... command (just need to init frontend first). Or instead treat them both as external and keep the command. In which use the named external network as shown above in your frontend docker compose as well.

SQLite mandatory environment variables for Docker Container

Grasshopper is a php web application that connects to a Bticino home automation gateway.
The two recommended ways to use it is either using the RPI image provided with all components installed or install it on a Linux machine with a LASP (Php, apache, sqlite) or LESP (nginx, Php, sqlite) setup.
I try to set grasshopper up in docker-compose by creating two services, the db and the apache webserver. For the db I've tried using the nouchka/sqlite3 image and the keinos/sqlite3 one. Both unfortunately come without documentation and I can nowhere find the mandatory environment variable as root user, psw and so on.
what I do have now only loads the site without DB connection:
version: "3"
services:
database:
image: keinos/sqlite3 #nouchka/sqlite3
#stdin_open: true
#tty: true
volumes:
- ./db/:/root/db/
restart: always
webapp:
build: .
#context: .
#dockerfile: Dockerfile-nginx
ports:
- "8080:80"
depends_on:
- database
restart: always
The Dockerfile:
FROM php:7.2-apache
COPY ./grasshopper_v5_application/ /var/www/html/
Grasshopper documentation: https://sourceforge.net/projects/grasshopperwebapp/files/Grasshopper%20V5%20Installation%20and%20Configuration%20Guide.pdf/download
Grasshopper files : https://sourceforge.net/projects/grasshopperwebapp/files/

Execute a plugin-installed WP-CLI command with Docker Compose

Intro:
I am trying to run a few WP-CLI commands for maintenance as a part of my release process on my production sites. I can execute the following commands against the docker-compose file below successfully.
docker-compose run wp-cli_collinmbarrett-com core update
docker-compose run wp-cli_collinmbarrett-com plugin update --all
docker-compose run wp-cli_collinmbarrett-com theme update --all
docker-compose run wp-cli_collinmbarrett-com db optimize
I have a plugin (WP-Sweep) installed on the site that adds its own WP-CLI command. When I try to run this command, it fails.
docker-compose run wp-cli_collinmbarrett-com sweep --all
/usr/local/bin/docker-entrypoint.sh: exec: line 15: sweep: not found
In a non-dockerized setup, I have verified that the WP-Sweep command for WP-CLI works successfully.
Question:
How can I run plugin-installed WP-CLI commands when running in a containerized environment with Docker Compose? Do I need to somehow make the WP-CLI container aware of the installed plugins other than having a shared volume?
My docker-compose.yml:
version: "3.7"
services:
wp_collinmbarrett-com:
image: wordpress:fpm-alpine
restart: always
networks:
- reverse-proxy
- collinmbarrett-com
depends_on:
- mariadb_collinmbarrett-com
volumes:
- collinmbarrett-com_files:/var/www/html
mariadb_collinmbarrett-com:
image: mariadb:latest
restart: always
networks:
- collinmbarrett-com
volumes:
- collinmbarrett-com_data:/var/lib/mysql
wp-cli_collinmbarrett-com:
image: wordpress:cli
networks:
- collinmbarrett-com
volumes:
- collinmbarrett-com_files:/var/www/html
networks:
reverse-proxy:
external:
name: wp-host_reverse-proxy
collinmbarrett-com:
volumes:
collinmbarrett-com_files:
collinmbarrett-com_data:
Full config on GitHub.
Not answering directly to your command needs (I didn't tried yet), but I wanted to share with you all the configurations I'm using in hope it helps you.
My docker-compose.yml has:
services:
...
# Mysql container
db:
...
# Wordpress container
wp:
...
wpcli:
image: wordpress:cli
user: "33:33"
volumes:
# necessary to write to the filesys
- ./php-config/phar.ini:/usr/local/etc/php/conf.d/phar.ini
- wp_app:/var/www/html
- /tmp/wp-temp:/tmp/wp-temp
environment:
HOME: /tmp/wp-temp
WORDPRESS_DB_HOST: db
WORDPRESS_DB_USER: $WORDPRESS_DB_USER
WORDPRESS_DB_PASSWORD: $WORDPRESS_DB_PASSWORD
WORDPRESS_DB_NAME: $WORDPRESS_DB_NAME
depends_on:
- db
- wp
volumes:
wp_app: {}
...
Please note that as mentioned on Running as an arbitrary user section in https://hub.docker.com/_/wordpress:
When running WP-CLI via the cli variants of this image, it is
important to note that they're based on Alpine, and have a default
USER of Alpine's www-data, whose UID is 82 (compared to the
Debian-based WordPress variants whose default effective UID is 33), so
when running wordpress:cli against an existing Debian-based WordPress
install, something like --user 33:33 is likely going to be necessary
(possibly also something like -e HOME=/tmp depending on the wp command
invoked and whether it tries to use ~/.wp-cli)
You will need to define WP-CLI user as www-data with user id and group id = 33. This is why I defined user: "33:33". Also, the command might need to download temporary content, so I defined a HOME environment setting. Please also note that HOME mapped in your Host should also be assigned with user 33:33 ownership ids, otherwise WP CLI can't write to the filesys.
Also, PHP.ini in the WPCLI image has the setting phar.readonly as On, so you need to override it. I've add a specific ./php-config/phar.ini file that has that override:
phar.readonly = Off
To execute a plugin installation I do, on my docker-compose.yml folder, the following command:
docker-compose run --rm wpcli plugin install wp-mail-smtp --force --allow-root
Please note that --force --allow-root are optional.

Docker with Symfony 4 - Unable to see the file changes

I'm working on a docker image for dev environment for a Symfony 4 application. I'm building it on alpine, php-fpm and nginx.
I have configured an application, but the performance was not great (~700ms) even for the simple hello world application, so I thought I can make it faster somehow.
First of all, I went for semantics configuration and configured the volumes to use cached configuration. Then, I moved vendor to separate volume as it caused the most of performance issues.
As a second thing I wanted to use docker-sync as the benchmarks looked amazing. I configured it and everything ran smoothly. But now I realized that the docker is not reacting to changes in code.
First, I thought that it has something to do with Symfony 4 cache, so I did connect to php's container and ran php bin/console cache:clear. Cache has been cleared, but the docker did not react to anything. I double-check the files on both web and php containers and the files are changed there. I'm wondering if there is something more I need to configure or why is Symfony not reacting to changes.
UPDATE
Symfony/Container does not react to changes even after complete image re-build and removal of semantics configuration and docker-sync. So, basically, it's plain docker with hello-world symfony 4 application and it does not react to changes. Changes are not even synced with container
Configuration:
# docker-compose-dev.yml
version: '3'
volumes:
symfony-sync:
external: true
services:
php:
build: build/php
expose:
- 9000
volumes:
- symfony-sync:/var/www/html/symfony
- ./vendor:/var/www/html/vendor
web:
build: build/nginx
restart: always
expose:
- 80
- 443
ports:
- 8080:80
- 8081:443
depends_on:
- php
volumes:
- symfony-sync:/var/www/html/symfony
- ./vendor:/var/www/html/vendor
networks:
default:
driver: bridge
ipam:
driver: default
config:
- subnet: 172.4.0.0/16
# docker-sync.yml
version: "2"
options:
verbose: true
syncs:
symfony-sync:
src: './symfony'
sync_excludes:
- '.git'
- 'composer.lock'
Makefile I use for running the app
start:
docker-sync stop
docker-sync clean
cd symfony
docker volume create --name=symfony-sync
cd ..
docker-compose -f docker-compose-dev.yml down
docker-compose -f docker-compose-dev.yml up -d
docker-sync start
stop:
docker-compose stop
docker-sync stop
I recommend to use dinghy instead docker4mac: https://github.com/codekitchen/dinghy
Have a try to this repo for example too: https://github.com/jorge07/symfony-4-es-cqrs-boilerplate
If this doesn't work the problem will be in you host or dockerfile. Be sure you don't enable opcache for development.

docker is not allowing to mount a directory into a drupal container

I am doing something very simple puting drupal in a docker container
volumes:
- /c/Users/mark/drupalb/sites/all/modules:/var/www/html/sites/all/modules
this directive which should mount home directory of my modules into the containers module directory doesnt work this seems like thing that people do everyday but how to resolves this
Not clear what your problem is. In the meantime here's a working drupal example
Example
The folowing compose file
└── docker-compose.yml
Runs two containers, one for drupal the other for the db:
$ docker volume create --name drupal_sites
$ docker-compose up -d
$ docker-compose ps
Name Command State Ports
--------------------------------------------------------------------------------
dockercompose_db_1 docker-entrypoint.sh mysqld Up 3306/tcp
dockercompose_web_1 apache2-foreground Up 0.0.0.0:8080->80/tcp
Note how the volume used to store the drupal sites is created separately, defaults to local storage but can be something more exotic to fit your needs
docker-compose.yml
version: '2'
services:
db:
image: mysql
environment:
- MYSQL_ROOT_PASSWORD=letmein
- MYSQL_DATABASE=drupal
- MYSQL_USER=drupal
- MYSQL_PASSWORD=drupal
volumes:
- /var/lib/mysql
web:
image: drupal
depends_on:
- db
ports:
- "8080:80"
volumes:
- drupal_sites:/var/www/html/sites
- /var/www/private
volumes:
drupal_sites:
external: true

Resources