Docker Compose com multiplos containers de websites na porta 80
Galera, aqui vamos abordar a configuração de containers trabalhando como servidor de multiplos websites na porta 80, como todos sabemos podemos utilizar somente uma porta 80 por Docker Host, para conseguir contornar esta limitação vamos configurar o Nginx como proxy reverso dando suporte a duas aplicações: WordPress e Drupal. Eu escolhi estas duas aplicações pois são bem comuns e em alguns casos vamos precisar ter rodando ambas em um mesmo Docker Host.
O que eu vou utilizar:
- Ip do Docker Host: 10.3.0.91
- Endereço para o Wordpress: wordpress.dqs.local
- Endereço para o Drupal: drupal.dqs.local
- Docker Compose: version 1.24.1, build 4667896b
Configurando o Docker Compose para o Systemd
Vamos criar o arquivo que vai manipular os serviços do docker-compose
vim /etc/systemd/system/docker-compose@.service [Unit] Description=%i service with docker compose Requires=docker.service After=docker.service [Service] Restart=always #Diretório que vai armazenar os arquivos de compose WorkingDirectory=/srv/docker/compose/%i # Remove containers antigos, images e volumes # Sempre tente manter a sua estrutura de docker organizada e sem danglings #ExecStartPre=/usr/local/bin/docker-compose down -v #ExecStartPre=/usr/local/bin/docker-compose rm -fv ## Habilitar os comandos abaixo caso queira sempre garantir que não temos dangling volumes/netwoks/containers #ExecStartPre=-/bin/bash -c 'docker volume ls -qf "name=%i_" | xargs docker volume rm' #ExecStartPre=-/bin/bash -c 'docker network ls -qf "name=%i_" | xargs docker network rm' #ExecStartPre=-/bin/bash -c 'docker ps -aqf "name=%i_*" | xargs docker rm' # Subindo o Compose ExecStart=/usr/bin/docker-compose up # Compose down, remove containers e volumes #ExecStop=/usr/bin/docker-compose down -v # Parando o Compose ExecStop=/usr/bin/docker-compose down [Install] WantedBy=multi-user.target
Agora vamos criar o diretório para armazenar os arquivos de compose
mkdir -p /srv/docker/compose/
Agora vamos criar o diretório para armazenar os dados dos containers
mkdir -p /srv/docker/data
Agora vamos criar um serviço para testar, vamos começar criando o diretório para armazenar o nosso novo serviço.
mkdir -p /srv/docker/compose/proxy_reverso
Configurando o docker-compose.yml
Agora vamos criar o nosso docker-compose file que vai controlar os serviços: Nginx, Wordpress, MySQL, Drupal e PostgreSQL.
vim /srv/docker/compose/proxy_reverso/docker-compose.yml version: '3' services: reverseproxy: image: reverseproxy:v1 build: context: '.' dockerfile: Dockerfile ports: - 80:80 networks: - wp_net - drupal_net restart: always db-wp: container_name: db-wp image: mysql:5.7 volumes: - ${DATA_DIR_MYSQL-/srv/docker/data/wordpress/data}:/var/lib/mysql environment: MYSQL_ROOT_PASSWORD: 1234 MYSQL_DATABASE: wordpress MYSQL_USER: wordpress MYSQL_PASSWORD: wordpress networks: - wp_net restart: always wp-web: container_name: wp-web volumes: - ${DATA_DIR_WP-/srv/docker/data/wordpress/html}:/var/www/html depends_on: - reverseproxy - db-wp image: wordpress environment: WORDPRESS_DB_HOST: db-wp:3306 WORDPRESS_DB_USER: wordpress WORDPRESS_DB_PASSWORD: wordpress networks: - wp_net restart: always drupal: container_name: drupal-web image: drupal:8-apache volumes: - drupal-modules:/var/www/html/modules - drupal-profiles:/var/www/html/profiles - drupal-themes:/var/www/html/themes - drupal-sites:/var/www/html/sites depends_on: - reverseproxy - db-drupal networks: - drupal_net restart: always db-drupal: container_name: db-drupal image: postgres:10 environment: POSTGRES_PASSWORD: example volumes: - db_data:/var/lib/postgresql/data networks: - drupal_net restart: always volumes: drupal-modules: drupal-profiles: drupal-sites: drupal-themes: db_data: networks: wp_net: drupal_net:
Aqui temos 5 serviços:
- reverseproxy:
- Vai ser gerado do Dockerfile
- Expoe a porta 80 para que possamos utilizar o serviço do Nginx como proxy
- Utiliza a network do wordpress e do drupal
- db-wp:
- Utiliza a versão 5.7 do MySQL
- Armazena os dados em um volume pré definido
- Temos as configurações básicas do MySQL
- Utiliza a network wp_net
- wp-web:
- Utiliza a ultima versão do Wordpress
- Armazena os dados em um volume pré definido
- Depende do reverseproxy e do db-wp
- Temos as configurações básicas do BD para o Wordpress.
- Utiliza a network wp_net
- drupal:
- Utiliza a ultima versão do 8 do Drupal
- Armazena os dados em volumes definidos pelo Docker
- Depende do reverseproxy e do db-drupal
- Utiliza a network drupal_net
- db-drupal:
- Utiliza a ultima versão do 10 do postgresql
- Armazena os dados em volumes definidos pelo Docker
- Utiliza a network drupal_net
Agora vamos criar o Dockerfile para o Nginx
vim /srv/docker/compose/proxy_reverso/Dockerfile # Vamos utilizar o Nginx do Alpine FROM nginx:alpine # Arquivo de configuração para o Nginx COPY nginx.conf /etc/nginx/nginx.conf
Agora vamos criar o arquivo de controle do Nginx
vim /srv/docker/compose/proxy_reverso/nginx.conf worker_processes 1; events { worker_connections 1024; } http { sendfile on; upstream docker-wordpress { server wp-web:80; } upstream docker-drupal { server drupal-web:80; } server { listen 80; server_name wordpress.dqs.local; location / { proxy_pass http://docker-wordpress; proxy_redirect off; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Host $server_name; } } server { listen 80; server_name drupal.dqs.local; location / { proxy_pass http://docker-drupal; proxy_redirect off; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Host $server_name; } } }
Aqui temos 2 servidores web que vamos mandar as requisições:
- docker-wordpress
- Container: wp-web
- Porta: 80
- docker-drupal
- Container: drupal-web
- Porta: 80
Quando vamos configurar o proxy reverso para websites notem que eu não configurei portas para os servidores web somente para o proxy, desta forma o proxy vai encaminhar as requisições pelas redes que demos acesso a ele sem precisarmos expor as portas para o Docker Host.
Agora vamos testar o nosso docker-compose.yml
cd /srv/docker/compose/proxy_reverso && docker-compose config networks: drupal_net: {} wp_net: {} services: db-drupal: container_name: db-drupal environment: POSTGRES_PASSWORD: example image: postgres:10 networks: drupal_net: null restart: always volumes: - db_data:/var/lib/postgresql/data:rw db-wp: container_name: db-wp environment: MYSQL_DATABASE: wordpress MYSQL_PASSWORD: wordpress MYSQL_ROOT_PASSWORD: 1234 MYSQL_USER: wordpress image: mysql:5.7 networks: wp_net: null restart: always volumes: - /srv/docker/data/wordpress2/data:/var/lib/mysql:rw drupal: container_name: drupal-web depends_on: - db-drupal - reverseproxy image: drupal:8-apache networks: drupal_net: null restart: always volumes: - drupal-modules:/var/www/html/modules:rw - drupal-profiles:/var/www/html/profiles:rw - drupal-themes:/var/www/html/themes:rw - drupal-sites:/var/www/html/sites:rw reverseproxy: build: context: /srv/docker/compose/nginx-reverse/reverse_proxy dockerfile: Dockerfile image: reverseproxy:v1 networks: drupal_net: null wp_net: null ports: - 80:80/tcp restart: always wp-web: container_name: wp-web depends_on: - db-wp - reverseproxy environment: WORDPRESS_DB_HOST: db-wp:3306 WORDPRESS_DB_PASSWORD: wordpress WORDPRESS_DB_USER: wordpress image: wordpress networks: wp_net: null restart: always volumes: - /srv/docker/data/wordpress2/html:/var/www/html:rw version: '3.0' volumes: db_data: {} drupal-modules: {} drupal-profiles: {} drupal-sites: {} drupal-themes: {}
Agora vamos execuar o build da imagem do reverseproxy
cd /srv/docker/compose/proxy_reverso && docker-compose build db-wp uses an image, skipping wp-web uses an image, skipping db-drupal uses an image, skipping drupal uses an image, skipping Building reverseproxy Step 1/2 : FROM nginx:alpine ---> 4d3c246dfef2 Step 2/2 : COPY nginx.conf /etc/nginx/nginx.conf ---> 249070beb1bc Successfully built 249070beb1bc Successfully tagged reverseproxy:v1
Agora vamos subir os serviços
docker-compose up -d Creating network "reverse_proxy_wp_net" with the default driver Creating network "reverse_proxy_drupal_net" with the default driver Creating volume "reverse_proxy_drupal-modules" with default driver Creating volume "reverse_proxy_drupal-profiles" with default driver Creating volume "reverse_proxy_drupal-sites" with default driver Creating volume "reverse_proxy_drupal-themes" with default driver Creating volume "reverse_proxy_db_data" with default driver Creating db-wp ... done Creating db-drupal ... done Creating reverse_proxy_reverseproxy_1 ... done Creating drupal-web ... done Creating wp-web ... do
Agora vamos listar os serviços, o comando abaixo funciona somente se estiver no mesmo diretório do docker-compose.yml
docker-compose ps Name Command State Ports ------------------------------------------------------------------------------------------- db-drupal docker-entrypoint.sh postgres Up 5432/tcp db-wp docker-entrypoint.sh mysqld Up 3306/tcp, 33060/tcp drupal-web docker-php-entrypoint apac ... Up 80/tcp reverse_proxy_reverseproxy_1 nginx -g daemon off; Up 0.0.0.0:80->80/tcp wp-web docker-entrypoint.sh apach ... Up 80/tcp
Agora na máquina cliente (que vai acessar pelo navegador) vamos criar duas entradas no /etc/hosts para podermos testar o proxy reverso. Caso tenha um DNS na rede insira as entradas no seu arquivo de dns.
sudo vim /etc/hosts [...] 10.3.0.91 wordpress.dqs.local 10.3.0.91 drupal.dqs.local
Configurando o WordPress
Precisamos acessar: http://wordpress.dqs.local
Configurando:
- Na primeira página
- Selecione o idioma: English (United States) e selecione Continue
- Na segunda página
- Site Title: Nome do Site
- Username: admin
- Password: 21smvOgCUdRyGzKO8O
- Your Email: douglas.q.santos@gmail.com
- Selecione Install Wordpress
- Na terceira página
- Selecione Log In
- Na quarta página
- informe o usuário e senha para efetuar o login
Configurando o Drupal
Agora vamos acessar: http://drupal.dqs.local para configurar o Drupal
- Na primeira página
- Choose language: Selecione o Idioma (English) e click em Save and Continue
- Na segunda página
- Select an installation profile: Standard e click em Save and Continue
- Na terceira página
- Database type: PostgreSQL
- Database name: postgres
- Database username: postgres
- Database password: example
- Host (under Advanced Options): db-drupal
- Click em Save and continue
- Na quarta página
- Site name: Nome do Site
- Site email address: douglas.q.santos@gmail.com
- Username: admin
- Password: 4bwbBaF4Pt62mz4w
- Confirm password: 4bwbBaF4Pt62mz4w
- Email address: douglas.q.santos@gmail.com
- Default country: Brazil
- Default time zone: Sao Paulo
- Agora click em Save and continue.
Habilitando o serviço no Systemd
Agora vamos parar os serviços do Docker
cd /srv/docker/compose/proxy_reverso && docker-compose down
Agora vamos habilitar o serviço do Nginx para o serviço do Docker Compose
systemctl enable docker-compose@reverse_proxy
Para subir o serviços podemos executar
systemctl start docker-compose@reverse_proxy
Agora podemos consultar o status dos nossos serviços
systemctl status docker-compose@reverse_proxy -l ● docker-compose@reverse_proxy.service - reverse_proxy service with docker compose Loaded: loaded (/etc/systemd/system/docker-compose@.service; enabled; vendor preset: disabled) Active: active (running) since Qui 2019-10-10 15:47:55 -03; 9s ago Process: 19728 ExecStop=/usr/bin/docker-compose down (code=exited, status=200/CHDIR) Main PID: 19749 (docker-compose) CGroup: /system.slice/system-docker\x2dcompose.slice/docker-compose@reverse_proxy.service ├─19749 /usr/bin/docker-compose up └─19750 /usr/bin/docker-compose up Out 10 15:47:59 centos7.dqs.local docker-compose[19749]: db-drupal | 2019-10-10 18:47:57.821 UTC [22] LOG: database system was shut down at 2019-10-10 18:45:23 UTC Out 10 15:47:59 centos7.dqs.local docker-compose[19749]: db-drupal | 2019-10-10 18:47:57.834 UTC [1] LOG: database system is ready to accept connections Out 10 15:47:59 centos7.dqs.local docker-compose[19749]: drupal-web | AH00558: apache2: Could not reliably determine the server's fully qualified domain name, using 192.168.48.4. Set the 'ServerName' directive globally to suppress this message Out 10 15:47:59 centos7.dqs.local docker-compose[19749]: drupal-web | AH00558: apache2: Could not reliably determine the server's fully qualified domain name, using 192.168.48.4. Set the 'ServerName' directive globally to suppress this message Out 10 15:47:59 centos7.dqs.local docker-compose[19749]: drupal-web | [Thu Oct 10 18:47:59.018666 2019] [mpm_prefork:notice] [pid 1] AH00163: Apache/2.4.25 (Debian) PHP/7.3.10 configured -- resuming normal operations Out 10 15:47:59 centos7.dqs.local docker-compose[19749]: drupal-web | [Thu Oct 10 18:47:59.018759 2019] [core:notice] [pid 1] AH00094: Command line: 'apache2 -D FOREGROUND' Out 10 15:47:59 centos7.dqs.local docker-compose[19749]: wp-web | AH00558: apache2: Could not reliably determine the server's fully qualified domain name, using 192.168.32.4. Set the 'ServerName' directive globally to suppress this message Out 10 15:47:59 centos7.dqs.local docker-compose[19749]: wp-web | AH00558: apache2: Could not reliably determine the server's fully qualified domain name, using 192.168.32.4. Set the 'ServerName' directive globally to suppress this message Out 10 15:47:59 centos7.dqs.local docker-compose[19749]: wp-web | [Thu Oct 10 18:47:59.677423 2019] [mpm_prefork:notice] [pid 1] AH00163: Apache/2.4.38 (Debian) PHP/7.3.10 configured -- resuming normal operations Out 10 15:47:59 centos7.dqs.local docker-compose[19749]: wp-web | [Thu Oct 10 18:47:59.677504 2019] [core:notice] [pid 1] AH00094: Command line: 'apache2 -D FOREGROUND'