Para uma melhor compreensão do material a seguir, é recomendável que você leia primeiro a
Postagem AnteriorConsidere um exemplo de desenvolvimento de um ambiente local que consiste em vários Nginx + PHP + MySql + phpMyAdmin. Esse pacote é muito popular e pode atender a várias necessidades padrão de um desenvolvedor comum.
Como na postagem anterior, a ênfase será voltada para o utilitário docker-compose do que para o docker em sua forma mais pura.
Então vamos lá!
Vamos começar com o docker-compose.yml, que está em uma pasta proxy separada:
docker-compose.yml para nginx-proxyversion: '3.0' services: proxy: image: jwilder/nginx-proxy ports: - 80:80 volumes: - /var/run/docker.sock:/tmp/docker.sock:ro networks: - proxy networks: proxy: driver: bridge
O arquivo apresentado descreve a configuração para criar um contêiner com o
proxy de nome com base na
imagem: imagem jwilder / nginx-proxy e criar uma rede com o mesmo nome. A diretiva de
redes indica a quais redes o contêiner está conectado, neste exemplo, esta é a nossa rede proxy.
Ao criar uma rede, a diretiva driver: bridge pode ser omitida. Um driver de ponte é o driver padrão. Este contêiner se comunicará pela rede com outros contêineres.
A imagem jwilder / nginx-proxy é básica e obtida, e o
Docker Hub também fornece uma descrição bastante extensa e detalhada de seu uso. O princípio de operação do nginx-proxy é bastante simples: ele acessa informações sobre a execução de contêineres por meio de um soquete de docker encaminhado, analisa a presença de uma variável de ambiente com o nome VIRTUAL_HOST e redireciona solicitações do host especificado para o contêiner para o qual a variável de ambiente especificada está definida.
Iniciamos o proxy com o comando docker-compose up -d já conhecido, observamos a seguinte saída:
Creating network "proxy_proxy" with driver "bridge" Creating proxy_proxy_1 ... done
Esta conclusão nos informa que, no início, a rede proxy_proxy foi criada e, em seguida, o contêiner proxy_proxy_1 foi criado. O nome da rede é obtido do nome da pasta na qual o arquivo docker-compose.yml estava localizado, tenho um proxy e o nome da rede com o mesmo nome.
Se você digitar o
comando docker network ls , veremos uma lista de redes docker em nosso sistema e uma delas deve ser proxy_proxy.
O nome do contêiner é criado com o mesmo princípio que o nome da pasta mais o nome e o número do serviço, o que permite que contêineres com nomes semelhantes não sejam duplicados.
Usando a diretiva
container_name , você pode especificar explicitamente o nome do contêiner, mas considero esta uma função bastante inútil. Isso será discutido em mais detalhes nas próximas postagens.
Crie um segundo docker-compose.yml com o seguinte conteúdo:
docker-compose.yml para outros serviços version: '3.0' services: nginx: image: nginx environment: - VIRTUAL_HOST=site.local depends_on: - php volumes: - ./docker/nginx/conf.d/default.nginx:/etc/nginx/conf.d/default.conf - ./html/:/var/www/html/ networks: - frontend - backend php: build: context: ./docker/php volumes: - ./docker/php/php.ini:/usr/local/etc/php/php.ini - ./html/:/var/www/html/ networks: - backend mysql: image: mysql:5.7 volumes: - ./docker/mysql/data:/var/lib/mysql environment: MYSQL_ROOT_PASSWORD: root networks: - backend phpmyadmin: image: phpmyadmin/phpmyadmin:latest environment: - VIRTUAL_HOST=phpmyadmin.local - PMA_HOST=mysql - PMA_USER=root - PMA_PASSWORD=root networks: - frontend - backend networks: frontend: external: name: proxy_proxy backend:
O que é anunciado aqui?
Quatro serviços estão listados: nginx, php, mysql e phpmyadmin. E duas redes. Uma rede proxy, chamada de front-end, é anunciada como uma rede externa e uma nova rede de back-end interna. O driver para ele não está especificado, como escrevi anteriormente, o driver padrão do tipo bridge será usado.
nginx
Tudo deve ficar claro aqui. Usamos a imagem básica com o hub docker. A variável de ambiente é necessária para o proxy funcionar e informa em que endereço o contêiner deve estar acessível. A opção depend_on indica a dependência desse contêiner no contêiner php. Isso significa que o contêiner php será lançado antecipadamente e, depois dele, o contêiner nginx dependente dele será lançado. Em seguida, encaminhamos a configuração para o nosso nginx. Será um pouco mais baixo e monte a pasta com html. Também observamos que o contêiner tem acesso a duas redes ao mesmo tempo. Ele deve comunicar os proxies da rede front-end e o php da rede back-end. Em princípio, seria possível colocar todos os contêineres na mesma rede front-end, mas acredito que essa separação é mais correta.
default.nginx server { listen 80; server_name_in_redirect off; access_log /var/log/nginx/host.access.log main; root /var/www/html/; location / { try_files $uri /index.php$is_args$args; } location ~ \.php$ { try_files $uri =404; fastcgi_split_path_info ^(.+\.php)(/.+)$; fastcgi_pass php:9000; fastcgi_index index.php; include fastcgi_params; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_param PATH_INFO $fastcgi_path_info; } location ~ /\.ht { deny all; } }
default.nginx é uma configuração do nginx que é encaminhada para o contêiner. O ponto chave aqui é a diretiva
fastcgi_pass php: 9000 . Ele define o endereço do servidor FastCGI. O endereço pode ser especificado como um nome de domínio ou endereço IP e porta.
php: 9000 - o nome do serviço é o endereço do servidor FastCGI. O Nginx acessando o php receberá o endereço IP do contêiner no qual o php está sendo executado. A porta 9000 é uma porta padrão, declarada ao criar o contêiner base. Essa porta está disponível para o nginx pela rede, mas não está disponível na máquina host, pois não foi encaminhada.
php
É incomum que uma imagem não seja indicada. Em vez disso, ele cria sua própria imagem diretamente do arquivo de composição. A diretiva de contexto aponta para a pasta na qual o Dockerfile está localizado.
Dockerfile FROM php:7.3.2-fpm RUN apt-get update && apt-get install -y \ libzip-dev \ zip \ && docker-php-ext-configure zip --with-libzip \ && docker-php-ext-install zip \ && docker-php-ext-install mysqli COPY --from=composer:latest /usr/bin/composer /usr/bin/composer WORKDIR /var/www/html
O Dockerfile afirma que a compilação usa a imagem básica do php: 7.3.2-fpm, então os comandos para instalar extensões php são executados. Em seguida, o compositor é copiado de outra imagem base e o diretório de trabalho do projeto é definido. Vou considerar questões de montagem com mais detalhes em outras postagens.
Além disso, o arquivo php.ini e a pasta html do nosso projeto são lançados dentro do contêiner.
Observe que o php está localizado na rede de back-end e, por exemplo, o proxy não pode mais acessá-lo.
mysql
A imagem base do mysql é obtida com a tag 5.7, responsável pela versão do mysql. A pasta ./docker/mysql/data é usada para armazenar arquivos de banco de dados (você nem precisa criá-lo, ele é criado na inicialização). E através das variáveis de ambiente, a senha é definida para o usuário root, também root.
O banco de dados está localizado na rede de back-end, o que lhe permite manter contato com o php. A imagem base usa a porta padrão 3306. Ela está disponível na rede docker para php, mas não está disponível na máquina host. Se você encaminhar para esta porta, poderá conectar-se a ela, por exemplo, a partir do mesmo PHPSTORM. Mas se a interface phpmyadmin for suficiente para você, você não poderá fazer isso.
phpmyadmin
A imagem oficial do phpmyadmin. As variáveis de ambiente usam VIRTUAL_HOST para interagir com o proxy, semelhante ao nginx. PMA_USER e PMA_PASSWORD acessam o banco de dados. E PMA_HOST o próprio banco de dados do host. Mas este não é o host local, como geralmente é o caso, mas o mysql. I.e. a comunicação com o banco de dados está disponível pelo nome de seu serviço, ou seja, mysql. O contêiner phpmyadmin pode se comunicar com o banco de dados, porque possui uma conexão com a rede front-end.
Iniciamos os serviços com o comando usual: docker-compose -d.
Vemos a seguinte saída:
Lançamento do serviço Creating network "lesson2_backend" with the default driver Building php Step 1/4 : FROM php:7.3.2-fpm ---> 9343626a0f09 Step 2/4 : RUN apt-get update && apt-get install -y libzip-dev zip && docker-php-ext-configure zip --with-libzip && docker-php-ext-install zip && docker-php-ext-install mysqli ---> Using cache ---> 5e4687b5381f Step 3/4 : COPY --from=composer:latest /usr/bin/composer /usr/bin/composer ---> Using cache ---> 81b9c665be08 Step 4/4 : WORKDIR /var/www/html ---> Using cache ---> 3fe8397e92e6 Successfully built 3fe8397e92e6 Successfully tagged lesson2_php:latest Pulling mysql (mysql:5.7)... 5.7: Pulling from library/mysql fc7181108d40: Already exists 787a24c80112: Already exists a08cb039d3cd: Already exists 4f7d35eb5394: Already exists 5aa21f895d95: Already exists a742e211b7a2: Already exists 0163805ad937: Already exists 62d0ebcbfc71: Pull complete 559856d01c93: Pull complete c849d5f46e83: Pull complete f114c210789a: Pull complete Digest: sha256:c3594c6528b31c6222ba426d836600abd45f554d078ef661d3c882604c70ad0a Status: Downloaded newer image for mysql:5.7 Creating lesson2_php_1 ... done Creating lesson2_mysql_1 ... done Creating lesson2_phpmyadmin_1 ... done Creating lesson2_nginx_1 ... done
Vemos que, no início, a rede lesson2_backend é criada, a imagem php é montada, as imagens que ainda não estão no sistema (pull) podem ser baixadas e os serviços descritos são realmente lançados.
O toque final, para que tudo funcione, essa adição aos domínios hosts ou sites.local e phpmyadmin.local.
O conteúdo de index.php pode ser o seguinte:
Aqui, verificamos se a conexão da extensão php - mysqli, que foi adicionada durante a montagem do Dockerfile, está correta.
E observe que, para a conexão com o contêiner, o nome do serviço é usado - mysql.
A estrutura de todo o projeto foi a seguinte:
Estrutura do projeto habr/lesson2$ tree . ├── docker │ ├── mysql │ │ └── data │ ├── nginx │ │ └── conf.d │ │ └── default.nginx │ └── php │ ├── Dockerfile │ └── php.ini ├── docker-compose.yml ├── html │ └── index.php └── proxy └── docker-compose.yml