Hello everyone! I will try to describe, without going into complicated terms, how to quickly and easily raise a site in Docker using docker-compose.
First step
First, we need the site itself. Let's assume that we already have some index.php that sends "Hello world" to the browser. Let's also assume that you already have Docker installed.
Step two: create docker-compose.yml
Docker containers are not virtual machines, they are just some allocated space. We need to decide which ones we need.
To begin with, three should be enough for us: the first is a regular mysql. The second is phpmyadmin. The third is our application.
First, create a db folder next to the app folder, and then create a docker-compose.yml file in the root.
In the db folder, mysql will make its own database files so that they are not lost if you suddenly rebuild containers. Base folder, yes.
The structure looks like this:

Well, the docker-compose.yml itself has the following content:
version: '3'
services:
db: #add a container named db here
image: 'mysql:latest' #take the last image
environment:
MYSQL_ROOT_PASSWORD: 12345 #here you must set a password for root
command: mysqld --default-authentication-plugin=mysql_native_password
ports:
- '3306:3306' #port for mysql
volumes:
- './db:/var/lib/mysql' #we say that the db folder is forwarded inside the container and will be used instead of /var/lib/mysql
networks:
- default #we tell the container to use the default network
phpmyadmin: #container with phpmyadmin
image: phpmyadmin/phpmyadmin
links:
- 'db:db' #make a link
ports:
- '8000:80' #we put the 80th port FROM the container on the 8000th port in our system
environment:
PMA_HOST: db #default host for db
PMA_PORT: 3306 #default port for db
app: #our main container with the site
build: .
ports:
- '80:80' #we plant the 80 port from the container on the 80 port of our computer. Those. it turns out that we can get where we need from the browser at the link http://localhost
volumes:
- './app:/var/www/html/' #we say that the app folder will be used instead of /var/www/html
restart: always #always restart if container crashed or exited
links:
- db
networks:
- default
volumes:
persistent: null
Third step: creating the Dockerfile
Now we need to determine what kind of container we will have and what will be in it. To do this, we also create a Dockerfile at the root and fill it with commands to install nginx and php.
Dockerfile:
FROM ubuntu:20.04 as intermediate
# Set the default Moscow time inside the container
RUN ln -snf /usr/share/zoneinfo/"Europe/Moscow" /etc/localtime && echo "Europe/Moscow" > /etc/timezone
# Install php and nginx packages via apt (this is the default for ubuntu)
RUN apt-get update \
&& apt-get install -y nginx php7.4 php7.4-cli php7.4-common php7.4-curl php7.4-dev php7.4-mysql php7.4-fpm
# We take from our conf folder (we will create a little later) the config, which we put inside and put it along the path / etc / nginx / sites-available / default
COPY conf/nginx.conf /etc/nginx/sites-available/default
# We need an entrypoint.sh script that will run indefinitely and prevent the container from stalling
COPY conf/entrypoint.sh /entrypoint.sh
# We also give him a little bit of rights
RUN chmod a+x /entrypoint.sh
ENTRYPOINT ["/entrypoint.sh"]
Fourth step: nginx.conf and entrypoint.sh
Before creating these files, we need the conf folder. The structure ultimately comes out like this:
In the file entrypoint.sh we hang the launch of php-fpm, nginx and reading the log.
#!/bin/bash echo "Running nginx & php-fpm" nginx && php-fpm7.4 # Here we hang up an endless view of the nginx log that will show errors while the container is running tail -f /var/log/nginx/error.log
Well, we fill the nginx.conf file with almost the stock configuration for such files.
server {
listen 80;
listen [::]:80;
server_name localhost;
root /var/www/html/;
location / {
try_files $uri /index.php$is_args$args;
}
location ~ ^/index\.php(/|$) {
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_index index.php;
fastcgi_pass unix:/var/run/php/php7.4-fpm.sock;
include fastcgi_params;
fastcgi_param PATH_INFO $fastcgi_path_info;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
internal;
}
location ~ \.php$ {
return 404;
}
error_log /var/log/nginx/project_error.log;
access_log /var/log/nginx/project_access.log;
}
First launch
Run
$ docker-compose up in the console and wait for everything to compose. :)Upon completion, you can also open a browser and make sure that our Hello world got to the right place.

Database connection
To test the database connection, let's try modifying our index.php file to look like this:
<?php
$host = 'db';
$user = 'root';
$password = '12345';
$database = 'mysql';
// we connect to the db container, if we don't connect, exit will work and we won't see the words "fire"
$link = mysqli_connect($host, $user, $password, $database)
or exit("Error " . mysqli_error($link));
echo "Fire, connection to database is successful";
// close the connection
mysqli_close($link);
We check:

