Consider an example of a sweep of the local environment consisting of a bundle of Nginx + PHP + MySql + phpMyAdmin. This bundle is very popular and can satisfy a number of standard needs of an ordinary developer.
As in the last post, the emphasis will be shifted towards the docker-compose utility than the docker in its pure form.
So let's go!
Let's start with the docker-compose.yml, which is located in a separate proxy folder:
')
docker-compose.yml for 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
The presented file describes the configuration for creating a single container with the
proxy name based on the
image: jwilder / nginx-proxy and creating a network with the same name. The
networks directive indicates which networks the container is connected to, in this example, it is our proxy network.
When creating a network, the driver: bridge directive could not be specified. The bridge driver is the default driver. This container will communicate over the network with other containers.
The jwilder / nginx-proxy image is basic and taken, and the
Docker Hub also contains a rather extensive and detailed description of its use. The principle of operation of nginx-proxy is quite simple, it gains access to information about running containers through a forked docker socket, analyzes the presence of an environment variable named VIRTUAL_HOST, and redirects requests from the specified host to a container that has this environment variable set.
We launch the proxy by the well-known docker-compose up -d command and observe the following output:
Creating network "proxy_proxy" with driver "bridge" Creating proxy_proxy_1 ... done
This conclusion informs us that at the beginning the network was created proxy_proxy, and then the container proxy_proxy_1 was created. The network name was obtained from the name of the folder in which the docker-compose.yml file was located, I have this proxy and the network name of the same name.
If we enter the
docker network ls command , we will see a list of the dockerβs networks on our system and one of them should be proxy_proxy.
The name of the container is built on the same principle as the name of the folder plus the name of the service and a number that allows containers with similar names not to be duplicated. Through the directive
container_name, you can set the name of the container explicitly, but I think this is a rather useless function. More will be discussed in the following posts.
Create a second docker-compose.yml with the following content:
docker-compose.yml for other services 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:
What is here announced?
Listed four services: nginx, php, mysql and phpmyadmin. And two networks. One proxy network, named frontend, is declared as an external network and a new internal network backend. The driver for it is not specified, as it was written earlier, the default driver of the bridge type will be used.
nginx
Here it should be all clear. Use the base image with the docker hub. The environment variable is needed for the proxy to work and tells it at what address the container should be accessible. The option depends_on indicates the dependency of this container on the php container. This means that the php container will be launched ahead, and after it, the dependent nginx container will be launched. Next, we forward the configuration for our nginx. It will be slightly lower and mount the folder with html. We also note that the container has access to two networks at once. It must communicate with both the proxy from the frontend network and php from the backend network. In principle, it would be possible to cram all the containers into one network of the frontend, but I adhere that this separation is more correct.
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 is the config for nginx, which is forwarded to the container. The key point here is the directive
fastcgi_pass php: 9000 . It sets the address of the FastCGI server. The address can be specified as a domain name or IP address, and a port.
php: 9000 - the service name is the address of the FastCGI server. Nginx addressing php will receive the IP address of the container in which php works. Port 9000 is a standard port, it is declared when creating the base container. This port is available for nginx over the network, but is not available on the host machine, since it was not forwarded.
php
It is unusual that the image is not specified. Instead, it builds its own image directly from the compose file. The context directive points to the folder where the Dockerfile is located.
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
The Dockerfile states that the base php image is used for the build: 7.3.2-fpm, then the commands are run to install the php extensions. Next, the composer is copied from another base image and the working directory for the project is set. More questions about the assembly will consider in other posts.
Also inside the container, the php.ini file and the html folder with our project are forwarded.
Note that php is on the backend network and, for example, a proxy can no longer access it.
mysql
It takes a basic mysql image with a tag 5.7, which is responsible for the version of mysql. The folder ./docker/mysql/data is used to store the database files (you donβt even need to create it, youβll need to create it yourself at startup). And through variable environments, a password is set for the root user, also root.
The base is in the backend network, which allows it to keep in touch with php. The basic image uses the standard port 3306. It is available on the dockerβs network for php, but is not available on the host machine. If you perform probros for this port, you can connect to it for example from the same PHPSTORM. But if the phpmyadmin interface is enough for you, then this can be done.
phpmyadmin
The official image of phpmyadmin. In environment variables, VIRTUAL_HOST is used to interact with the proxy, similar to nginx. PMA_USER and PMA_PASSWORD access to the database. And PMA_HOST host database itself. But this is not localhost, as usual, but mysql. Those. connection to the database is available by the name of its service, i.e. mysql. The phpmyadmin container can connect to the database, as it has a connection to the frontend network.
We start the services with the usual command: docker-compose -d.
We see the following conclusion:
Starting services 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
We see that at the beginning there is a creation of a network lesson2_backend, then the assembly of the php image, then it can download images that are not yet in the system (pull) and actually launch the described services.
The final touch to make it work is to add to hosts or domains site.local and phpmyadmin.local.
The contents of index.php can be as follows:
Here we check the correctness of the connection of the php extension - mysqli, which was added when building the Dockerfile.
And note that to communicate with the container, the service name is used - mysql.
The structure of the whole project is the following:
Project structure 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