docker-compose: share db connection to multiple websites - docker

I have a Docker setup serving two WordPress blogs with a proxy, and using the following structure and docker-compose file:
.
├── nginx-proxy
│   └── docker-compose.yml
└── blogs
   └── docker-compose.yml
docker-compose.yml
version: "3"
services:
db:
container_name: ${CONTAINER_DB_NAME}
image: mariadb:latest
restart: unless-stopped
volumes:
- ${DB_PATH}:/var/lib/mysql
environment:
MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
MYSQL_DATABASE: ${MYSQL_DATABASE}
MYSQL_USER: ${MYSQL_USER}
MYSQL_PASSWORD: ${MYSQL_PASSWORD}
wordpress1:
depends_on:
- db
container_name: ${CONTAINER_WP_NAME1}
image: wordpress:latest
restart: unless-stopped
volumes:
- ${WP_CORE}:/var/www/html
- ${WP_CONTENT}:/var/www/html/wp-content
- ./conf.d/php.ini:/usr/local/etc/php/conf.d/php.ini
environment:
WORDPRESS_DB_HOST: ${CONTAINER_DB_NAME1}:3306
WORDPRESS_DB_NAME: ${MYSQL_DATABASE1}
WORDPRESS_DB_USER: ${MYSQL_USER1}
WORDPRESS_DB_PASSWORD: ${MYSQL_PASSWORD1}
WORDPRESS_TABLE_PREFIX: ${WORDPRESS_TABLE_PREFIX1}
VIRTUAL_HOST: ${DOMAINS1}
LETSENCRYPT_HOST: ${DOMAINS1}
LETSENCRYPT_EMAIL: ${LETSENCRYPT_EMAIL1}
logging:
options:
max-size: ${LOGGING_OPTIONS_MAX_SIZE1:-200k}
wordpress2:
depends_on:
- db
container_name: ${CONTAINER_WP_NAME2}
image: wordpress:latest
restart: unless-stopped
volumes:
- ${WP_CORE}:/var/www/html
- ${WP_CONTENT}:/var/www/html/wp-content
- ./conf.d/php.ini:/usr/local/etc/php/conf.d/php.ini
environment:
WORDPRESS_DB_HOST: ${CONTAINER_DB_NAME2}:3306
WORDPRESS_DB_NAME: ${MYSQL_DATABASE2}
WORDPRESS_DB_USER: ${MYSQL_USER2}
WORDPRESS_DB_PASSWORD: ${MYSQL_PASSWORD2}
WORDPRESS_TABLE_PREFIX: ${WORDPRESS_TABLE_PREFIX2}
VIRTUAL_HOST: ${DOMAINS2}
LETSENCRYPT_HOST: ${DOMAINS2}
LETSENCRYPT_EMAIL: ${LETSENCRYPT_EMAIL2}
logging:
options:
max-size: ${LOGGING_OPTIONS_MAX_SIZE2:-200k}
networks:
default:
external:
name: ${NETWORK}
But I'd like to make it more maintainable. I want to refactor this in order to make a separate container to the mysql db, refactor each blog config to it's own docker-compose file and reference the db on each blog configuration, like so:
.
├── db
│   └── docker-compose.yml
├── blog1
│   └── docker-compose.yml
├── blog2
│ └── docker-compose.yml
└── blog3
└── docker-compose.yml
db container
version: "3"
services:
db:
container_name: ${CONTAINER_DB_NAME}
image: mariadb:latest
restart: unless-stopped
volumes:
- ${DB_PATH}:/var/lib/mysql
environment:
MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
MYSQL_DATABASE: ${MYSQL_DATABASE}
MYSQL_USER: ${MYSQL_USER}
MYSQL_PASSWORD: ${MYSQL_PASSWORD}
networks:
default:
external:
name: ${NETWORK}
blog1 container
version: "3"
services:
wordpress1:
depends_on:
- db // Does Docker knows this is db service I created outside it?
container_name: ${CONTAINER_WP_NAME1}
image: wordpress:latest
restart: unless-stopped
volumes:
- ${WP_CORE}:/var/www/html
- ${WP_CONTENT}:/var/www/html/wp-content
- ./conf.d/php.ini:/usr/local/etc/php/conf.d/php.ini
environment:
WORDPRESS_DB_HOST: ${CONTAINER_DB_NAME1}:3306
WORDPRESS_DB_NAME: ${MYSQL_DATABASE1}
WORDPRESS_DB_USER: ${MYSQL_USER1}
WORDPRESS_DB_PASSWORD: ${MYSQL_PASSWORD1}
WORDPRESS_TABLE_PREFIX: ${WORDPRESS_TABLE_PREFIX1}
VIRTUAL_HOST: ${DOMAINS1}
LETSENCRYPT_HOST: ${DOMAINS1}
LETSENCRYPT_EMAIL: ${LETSENCRYPT_EMAIL1}
logging:
options:
max-size: ${LOGGING_OPTIONS_MAX_SIZE1:-200k}
networks:
default:
external:
name: ${NETWORK}
... and so on.
I have no idea on how to handle the db connection. Today, I put a reference to it at the "depends_on" section, as the db service configuration lies on the same file as the blog. But how do I invoke the db instance when the sites are declared into separate files? Does Docker knows that the "db" is the db service declared externally to that file?
Any ideas would be great!

You can specify multiple compose files when running a docker compose command, you could for instance set up a single blog with:
docker-compose -f db.yml -f blog1.yml up
or all of them:
docker-compose -f db.yml -f blog1.yml -f blogX.yml up
Read more on how to specify multiple compose files
Note that you could also use an environment variable to specify your files:
COMPOSE_FILE=db.yml:blog1.yml docker-compose up
More here

The easiest way to set this up would be with a separate database per application. So split this out into blog1/docker-compose.yml and so on as you describe, but have each of those Compose files be self-contained, with its own db: and wordpress: services. You can then launch as many copies of this as you'd like, provided that (a) you set different published ports: for each copy, and (b) that you launch each copy from a differently-named directory.
You should also let Compose set container names for you; this will reduce the possibility of collisions. Delete the container_name: fields. Containers can still reach each other using their services: name as host names; for example, set WORDPRESS_DB_HOST: db:3306. There are docker-compose ... equivalents to most of the standard plain docker commands, but if you do need to directly interact with a container they'll usually be named things like blog1_db_1.

Related

Volume defined in docker-compose.yml shows up empty

I have the following in my docker-compose.yml file:
version: '3.9'
services:
db:
image: mysql:5.7
volumes:
- db_data:/var/lib/mysql
- db_import:/import
restart: always
ports:
- "3338:3306"
environment:
MYSQL_ROOT_PASSWORD: somewordpress
MYSQL_DATABASE: wordpress
MYSQL_USER: wordpress
MYSQL_PASSWORD: wordpress
volumes:
db_data: {}
db_import: {}
dist: {}
The problem is that even though I have a dump.sql file in my db_import folder (inside the same folder where docker-compose.yml resides), I find that docker-compose exec db ls -al /import shows an empty directory. I've tried restarting all docker containers without any improvement.
Why is this directory not passing my content through?
By writing:
volumes:
- db_data:/var/lib/mysql
- db_import:/import
(...)
volumes:
db_data: {}
db_import: {}
dist: {}
You created so called Named Volumes with names db_data, db_import and dist. Docker doesn't tell us where those volumes are stored (and we shouldn't care about that). That kind of volumes is used to share data between containers and they do not have access to anything from your host machine.
If you want to share files beetween your host and container you must use Mount Binds instead - syntax is almost identical, you just need to replace db_data and db_import with absolute paths to that directories:
version: '3.9'
services:
db:
image: mysql:5.7
volumes:
- /PATH/TO/db_data:/var/lib/mysql
- /PATH/TO/db_import:/import
restart: always
ports:
- "3338:3306"
environment:
MYSQL_ROOT_PASSWORD: somewordpress
MYSQL_DATABASE: wordpress
MYSQL_USER: wordpress
MYSQL_PASSWORD: wordpress
#volumes: That part isn't needed unless you use "dist" volume somewhere
# db_data: {}
# db_import: {}
# dist: {}

Docker - Adding new Wordpress container to existing SQL database container

I'm trying to understand or find information on how I would connect a new Wordpress container to an existing MariaDB container. I'm missing something. I can add a Wordpress instance while also creating the MariaDB container. See below.
services:
wordpress:
image: wordpress
restart: always
ports:
- 8282:80
environment:
WORDPRESS_DB_HOST: db
WORDPRESS_DB_USER: exampleuser
WORDPRESS_DB_PASSWORD: examplepass
WORDPRESS_DB_NAME: exampledb
volumes:
- ./:/var/www/html
links:
- db:db
db:
image: mariadb:latest
restart: always
container_name: mariadb
environment:
MYSQL_DATABASE: exampledb
MYSQL_USER: exampleuser
MYSQL_PASSWORD: examplepass
MYSQL_ROOT_PASSWORD: password
volumes:
- db:/var/lib/mysql
phpmyadmin:
image: phpmyadmin/phpmyadmin
restart: always
container_name: phpmyadmin
ports:
- "8081:80"
environment:
PMA_HOST: mariadb
volumes:
wordpress:
db:
phpmyadmin:```
After that has spun up and is good to go, I then attempt another docker-compose.yml (see below) and I cannot get the Wordpress instance to connect to the SQL instance.
```version: '3.7'
services:
wordpress:
image: wordpress
restart: always
container_name: wordup
ports:
- 8283:80
environment:
WORDPRESS_DB_HOST: 172.20.0.3
WORDPRESS_DB_USER: username
WORDPRESS_DB_PASSWORD: password
WORDPRESS_DB_NAME: wp2
volumes:
- ./:/var/www/html
volumes:
wp2:
How would I point the new WP instance to the database that I created on the MariaDB container? Is it possible to point new Docker Compose stacks to an already created DB without recreating a new DB? I know that it's not a good idea to share DB's across different applications, but I have a need to pull in data from one Wordpress site to another.
Thanks!
You can use Docker networks. You need to connect two docker-compose files to the same network and inside this network containers can reference each other by container name.
Here is more information about docker-compose networking in the documentation: https://docs.docker.com/compose/networking/#specify-custom-networks
Take a look at an example with two Nginx proxies that started using different docker-compose files. The first proxy redirects to the second one and then it redirects us to google.com.
First proxy docker-compose.yml
version: "3.9"
services:
first:
build: .
ports:
- "8081:80"
networks:
- "test-network"
networks:
test-network:
name: "test-network"
driver: "bridge"
First proxy ngnix.conf
events {}
http {
server {
location / {
proxy_pass http://second:80; # in second docker-compose file we're setting container_name to "second", thus we can reference second container by this name
}
}
}
Second proxy docker-compose.yml:
version: "3.9"
services:
second:
container_name: "second" # note, that we don't need to expose ports because we don't need to make this service visible to a host. But it's not restricted to expose ports. You can do so if you need.
build: .
networks:
- "test-network"
networks:
test-network:
name: "test-network"
driver: "bridge"
Second proxy ngnix.conf:
events {}
http {
server {
location / {
proxy_pass https://google.com;
}
}
}

How can I get a full Backup from a Docker Container

I'm new to Docker and created myself a Container using a Compose File.
Now I came to a point where I wanted to use my development result in production.
Is there any way to backup the whole content so that I can use it in a production environment ?
The compose file that I used to spin up my Container:
version: '3.3'
services:
db:
image: mysql:5.7
volumes:
- db_data:/var/lib/mysql
restart: always
environment:
MYSQL_ROOT_PASSWORD: myRootPassword
MYSQL_DATABASE: wordpress_oxygen
MYSQL_USER: wordpress_oxygen
MYSQL_PASSWORD: myDBPassword
wordpress:
depends_on:
- db
image: wordpress:latest
ports:
- "8000:80"
restart: always
environment:
WORDPRESS_DB_HOST: db:3306
WORDPRESS_DB_USER: wordpress
WORDPRESS_DB_PASSWORD: wordpress
WORDPRESS_DB_NAME: wordpress
volumes:
db_data: {}
Docker compose is not for production. For production try docker swarm.
Also you should add volume for wordpress, see example
https://hub.docker.com/_/wordpress
How backup volumes please see https://docs.docker.com/storage/volumes/#backup-restore-or-migrate-data-volumes

Duplicate of the same docker configuration with different projects

I have two different projects with the same docker configuration (docker-compose.yml), but different files.
├── a
│ ├── docker-compose.yml
│ └── Dockerfile
└── b
├── docker-compose.yml
└── Dockerfile
How is it possible to build containers with the same name but for different projects? I don't want to think of new names for each project if I work only on one project at the same time.
ERROR: for mysql Cannot create container for service mysql: Conflict. The container name "/mysql" is already in use by container "90a84268d483ec2bd5cf0feb7ab1972384941ba255a671c0cfd2b4017ce90682". You have to remove (or rename) that container to be able to reuse that name.
Docker-compose.yml
version: '3'
services:
nginx:
image: nginx:stable-alpine
container_name: nginx
ports:
- "8080:80"
volumes:
- ./src:/var/www/html
- ./nginx/default.conf:/etc/nginx/conf.d/default.conf
depends_on:
- php
- mysql
networks:
- laravel
mysql:
image: mysql:8.0.19
container_name: mysql
restart: unless-stopped
tty: true
ports:
- "3306:3306"
environment:
MYSQL_DATABASE: homestead
MYSQL_USER: homestead
MYSQL_PASSWORD: secret
MYSQL_ROOT_PASSWORD: secret
SERVICE_TAGS: dev
SERVICE_NAME: mysql
networks:
- laravel
php:
build:
context: .
dockerfile: Dockerfile
container_name: php
volumes:
- ./src:/var/www/html
ports:
- "9000:9000"
networks:
- laravel
Don't override container_name.

How can I get a copy of the volume data onto a folder on my desktop?

For example, say if my containers got deleted, and the rm - v removes the volumes , I want to be able to store the volume data locally on my machine. So that in future, if I were to create a new container(s) I would like to use this same volume data. In other words, I want to map a volume to a WP content and spin it back up when it is started.
version: '3.3'
services:
db:
image: mysql:5.7
volumes:
- db_data:/var/lib/mysql
restart: always
environment:
MYSQL_ROOT_PASSWORD: somewordpress
MYSQL_DATABASE: wordpress
MYSQL_USER: wordpress
MYSQL_PASSWORD: wordpress
wordpress:
depends_on:
- db
image: wordpress:latest
ports:
- "8000:80"
restart: always
environment:
WORDPRESS_DB_HOST: db:3306
WORDPRESS_DB_USER: wordpress
WORDPRESS_DB_PASSWORD: wordpress
WORDPRESS_DB_NAME: wordpress
volumes:
db_data: {}
services:
db:
volumes:
- db_data:/var/lib/mysql
volumes:
db_data:
driver: local
driver_opts:
o: bind
type: none
device: /disk1/myfolder-data
Check this for details

Resources