Мы продолжаем цикл обучающих статей для начинающих системных администраторов. В этом материале мы разберем Dockerfile, docker-compose и как поднять полноценный веб-сервер с помощью docker. Отмечу, что если вы являетесь опытным администратором, можете смело пропускать данный материал.

Эта статья призвана простыми словами объяснить, что такое контейнеры, виртуализация и все, что с этим связанно. Несмотря на то, что тема уже достаточно подробно отражена в сети, мы решили подробно описать общие стандарты администрирования с нуля, поскольку регулярно получаем большое количество базовых вопросов от людей, так или иначе, связанных с нашей сферой. Цель серии статей - лишь указать на нюансы в работе и защитить начинающих специалистов от базовых ошибок при настройке.

Предыдущие статьи обязательны к прочтению:

Настройка LEMP-сервера с помощью docker для простых проектов. Часть первая: База

Настройка LEMP-cервера с помощью docker для простых проектов. Часть вторая: docker-compose

Настройка LEMP-сервера для простых проектов. Инструкция для самых маленьких. Часть первая.

  1. DockerFile

  2. Начинаем писать Dockerfile.

  3. Dockerfile php8.1-fpm.

  4. Dockerfile mysql и nginx.

  5. Запуск docker-compose.

DockerFile

Dockerfile - это инструкция по сборке образа. В инструкции будут указаны команды, которые необходимо выполнить при сборке контейнера. 

Пример: Собрать образ php8.1-fpm с дополнительными пакетами libgeoip-dev, libmemcached-dev и установленными модулями geoip, mcrypt, memcached.

Основные команды.

Основные команды с помощью, которых и пишется Dockerfile:

  1. FROM - Указывается базовый образ из DockerHub.
    Пример: FROM PHP:7.4-cli

  2. ENV - Присваивание переменной.
    Пример: ENV DOMAIN=DOMAIN_NAME.com
    Теперь при вызове $DOMAIN автоматически будет вставляться DOMAIN_NAME.com.
    Используется редко. Так как все env можно присваивать в docker-compose.yml.

  3. COPY - Копирует файл или директорию в контейнер на этапе сборки образа. Сначала адрес файла/директории на хосте, далее адрес адрес в контейнере.
    Пример: COPY docker-entrypoint.sh /

  4. EXPOSE - Открываем порт в контейнере. Используется редко, так как все порты можно открывать в docker-compose.yml.
    Пример: EXPOSE 8080

  5. RUN - объявляет, что дальше идет команда.
    Пример: RUN apt-get update

  6. WORKDIR - рабочая директория. В данную директорию вы будете попадать при входе в директорию.
    Пример: WORKDIR /var/www

  7. CMD - значение по умолчанию для исполняемого контейнера. В Dockerfile может быть только один вызов CMD.
    Пример: Для контейнеров php-fpm необходимо, чтоб всегда работал php-fpm. Если php-fpm не работает, контейнер падает с ошибкой.
    CMD  ["php-fpm"]

  8. ENTRYPOINT - аналог CMD. Указывает запуск исполняемого файла в контейнере. Данный файл будет выполняться всегда при перезагрузке контейнера. Может быть указана одновременно с CMD.
    Пример: ENTRYPOINT ["/docker-entrypoint.sh"]
    При перезагрузке контейнера у нас всегда будет запускаться docker-entrypoint.sh.

Больше команд и информации о них в официальном мануале.

Слои Dockerfile.

Как собираются слои?

Docker берет образ из репозитория, после чего начинает записывать на него слои, которые описаны в Dockerfile.

В итоге у нас получается пирог из нескольких слоев. Все это собирается в образ, после чего запускается на сервере.

Пример: Запускаем установку curl и sendmail.

Получается такой тортик:

Важно знать, что при каждом запуске команд. Docker записывает новый слой. Чем больше слоев тем больше будет весить собранный образ, и тем дольше будет собираться контейнер. Поэтому всегда необходимо оптимизировать слои Dockerfile. Иначе вместо миниатюрного милого тортика он превратиться в огромный торт весов в 3G и сборкой в полчаса.

И вы со словами “Я несу тортик”. Понесете его на продакшен.

Как оптимизировать слои, мы поговорим после того, как напишем первый Dockerfile.

Начинаем писать Dockerfile.

Как писать хороший Dockerfile? Нам необходима тактика.

Тактика заключается в том, что мы заранее сделаем список из нужных нам пакетов, библиотек. После чего на основе данного списка протестируем запуск пакетов и напишем команды для Dockerfile.

Тактика:

  1. Cписок модулей, сервисов, пакетов, библиотек.

  2. Тестирование установки в контейнер

  3. Написание Команд для Dockerfile.

  4. Перенос результата в Dockerfile.

  5. Запуск контейнера

Dockerfile php8.1-fpm.

Пункт 1. Cписок модулей, сервисов, пакетов, библиотек.

Нам нужно знать, какие нам пакеты, сервисы, модули нужны в контейнеры. Мы составляем список всего, что нам нужно. В данных статьях мы разворачиваем php-fpm под wordpress, поэтому берем список модулей для php, которые необходимы для wordpress. С офф.сайт.

Нам необходимы модули:

exif,  imagick,  openssl,  zip, bcmath, filter, gd,  intl, curl, dom, fileinfo, hash, mbstring, xml, iconv, simplexml, sodium, xmlreader, zlib,  pcre.

Для начала нам необходимо проверить какие модули уже установлены в образе php8.1-fpm.

Запускаем сбор тестового образа простой командой из 1 статьи.

docker run -d php:8.1.5-fpm
docker run -d php:8.1.5-fpm
Unable to find image 'php:8.1.5-fpm' locally
8.1.5-fpm: Pulling from library/php
1fe172e4850f: Pull complete
012a3732d045: Pull complete
43092314d50d: Pull complete
4f615e42d863: Pull complete
f896b94fc405: Pull complete
86b8a98f8d70: Pull complete
71729f2ef2b8: Pull complete
b2cfcdf44abb: Pull complete
2440531c13bc: Pull complete
6e794559acbe: Pull complete
Digest: sha256:26d0e7a636a4fa140e5958110b6458fd0667a4a24069f0c60aca0d38df6d66ad
Status: Downloaded newer image for php:8.1.5-fpm
3ebf3e9aadb5be40fa10160979fc0a6524307e5078804323b3337b9bdf5d92b6

Проверяем:

docker ps
CONTAINER ID   IMAGE           COMMAND                  CREATED         STATUS         PORTS      NAMES
3ebf3e9aadb5   php:8.1.5-fpm   "docker-php-entrypoi…"   5 seconds ago   Up 2 seconds   9000/tcp   pensive_cray

Далее заходим в контейнер командой из первой статьи:

docker exec -it pensive_cray bash
@:/var/www/html#

Смотрим, какие модули установлены из коробки:

@:/var/www/html# php -m
[PHP Modules]
Core
ctype
curl
date
dom
fileinfo
filter
ftp
hash
iconv
json
libxml
mbstring
mysqlnd
openssl
pcre
PDO
pdo_sqlite
Phar
posix
readline
Reflection
session
SimpleXML
sodium
SPL
sqlite3
standard
tokenizer
xml
xmlreader
xmlwriter
zlib
[Zend Modules]

В контейнере нет модулей:

exif,  imagick,  openssl,  zip, bcmath, filter, gd,  intl, mcrypt

Уже есть в контейнере:

curl, dom, fileinfo, hash, mbstring, xml, iconv, simplexml, sodium, xmlreader, zlib,  pcre.

Список состоит из данных модулей exif, imagick, openssl, zip, bcmath, filter, gd,  intl, mcrypt. Их необходимо поставить в контейнер.

Пункт 2 и 3. Тестирование установки в контейнер и написание Команд для Dockerfile.

В контейнерах php для подключение модулей используются команды:

  1. docker-php-ext-install - установка модуля.

  2. docker-php-ext-configure - конфигурация модуля.

  3. docker-php-ext-enable - включение модуля.

  4. pecl install - установка модулей с помощью pecl.

Первый модуль из списка это exif. Пробуем ставить модули:

В контейнере запускаем:

docker-php-ext-install exif

Происходит установка:

:/var/www/html# docker-php-ext-install exif
Configuring for:
PHP Api Version:         20210902
Zend Module Api No:      20210902
Zend Extension Api No:   420210902
checking for grep that handles long lines and -e... /bin/grep
checking for egrep... /bin/grep -E
checking for a sed that does not truncate output... /bin/sed
checking for pkg-config... /usr/bin/pkg-config
checking pkg-config is at least version 0.9.0... yes
checking for cc... cc
checking whether the C compiler works... yes
checking for C compiler default output file name... a.out
checking for suffix of executables...
checking whether we are cross compiling... no
checking for suffix of object files... o
checking whether we are using the GNU C compiler... yes
checking whether cc accepts -g... yes
checking for cc option to accept ISO C89... none needed
checking how to run the C preprocessor... cc -E

Проверяем:

:/var/www/html# php -m | grep exif
exif

Модуль установлен!

Записываем команду в Dockerfile.

RUN docker-php-ext-install exif

Лайфхак: можете просто записывать команды в текстовый редактор. После чего все перенесете в Dockerfile. КЭП time!!!

Далее по списку это imagick.

Пробуем установить:

docker-php-ext-install imagick

Получаем ошибку:

/var/www/html# docker-php-ext-install imagick
error: /usr/src/php/ext/imagick does not exist

Не находит imagick. Модуля нет. 

Пробуем с помощью pecl:

pecl install imagick
downloading imagick-3.7.0.tgz ...
Starting to download imagick-3.7.0.tgz (360,138 bytes)
.........................................................................done: 360,138 bytes
33 source files, building
running: phpize
Configuring for:
PHP Api Version:         20210902
Zend Module Api No:      20210902
Zend Extension Api No:   420210902
Please provide the prefix of ImageMagick installation [autodetect] :
building in /tmp/pear/temp/pear-build-defaultuserDlaKao/imagick-3.7.0
running: /tmp/pear/temp/imagick/configure --with-php-config=/usr/local/bin/php-config --with-imagick
checking for grep that handles long lines and -e... /bin/grep
checking for egrep... /bin/grep -E
checking for a sed that does not truncate output... /bin/sed
checking for pkg-config... /usr/bin/pkg-config
checking pkg-config is at least version 0.9.0... yes
checking for cc... cc
checking whether the C compiler works... yes
checking for C compiler default output file name... a.out
checking for suffix of executables...
checking whether we are cross compiling... no
checking for suffix of object files... o
checking whether we are using the GNU C compiler... yes
checking whether cc accepts -g... yes
checking for cc option to accept ISO C89... none needed
checking how to run the C preprocessor... cc -E
checking for icc... no
checking for suncc... no
checking for system library directory... lib
checking if compiler supports -Wl,-rpath,... yes
checking build system type... x86_64-pc-linux-gnu
checking host system type... x86_64-pc-linux-gnu
checking target system type... x86_64-pc-linux-gnu
checking for PHP prefix... /usr/local
checking for PHP includes... -I/usr/local/include/php -I/usr/local/include/php/main -I/usr/local/include/php/TSRM -I/usr/local/include/php/Zend -I/usr/local/include/php/ext -I/usr/local/include/php/ext/date/lib
checking for PHP extension directory... /usr/local/lib/php/extensions/no-debug-non-zts-20210902
checking for PHP installed headers prefix... /usr/local/include/php
checking if debug is enabled... no
checking if zts is enabled... no
checking for gawk... no
checking for nawk... nawk
checking if nawk is broken... no
checking whether to enable the imagick extension... yes, shared
checking for pkg-config... /usr/bin/pkg-config
checking ImageMagick MagickWand API configuration program... checking Testing /usr/local/bin/MagickWand-config... Doesn't exist
checking Testing /usr/bin/MagickWand-config... Doesn't exist
checking Testing /usr/sbin/bin/MagickWand-config... Doesn't exist
checking Testing /opt/bin/MagickWand-config... Doesn't exist
checking Testing /opt/local/bin/MagickWand-config... Doesn't exist
checking Testing /opt/homebrew/bin/MagickWand-config... Doesn't exist
configure: error: not found. Please provide a path to MagickWand-config or Wand-config program.
ERROR: `/tmp/pear/temp/imagick/configure --with-php-config=/usr/local/bin/php-config --with-imagick' failed

Также получаем ошибку:

ERROR: `/tmp/pear/temp/imagick/configure --with-php-config=/usr/local/bin/php-config --with-imagick' failed

Начинаем искать данную ошибку в дебрях интернета, после чего находим ответ, что не хватает библиотек libmagickwand-dev и libmagickcore-dev.

Ставим библиотеки в контейнер:

apt-get install libmagickwand-dev libmagickcore-dev -y

Пробуем опять:

pecl install imagick

Видим, что модуль установлен.

Осталось только включить его:

docker-php-ext-enable imagick

Проверяем:

:/var/www/html# php -m | grep imagick
imagick

Модуль установлен!

В наш Dockerfile идут команды:

RUN apt-get install libmagickwand-dev libmagickcore-dev -y
RUN pecl install imagick
RUN docker-php-ext-enable imagick

Далее методом проб и ошибок получаем такие RUN:

Внимание! Рекомендуем попробовать самостоятельно поставить все оставшиеся модули, после чего сверить с тем, что у нас получилось.

Dockerfile RUN спойлер.
RUN docker-php-ext-install exif
RUN apt-get install libmagickwand-dev libmagickcore-dev -y
RUN pecl install imagick
RUN docker-php-ext-enable imagick
RUN PHP_OPENSSL=yes
RUN docker-php-ext-install xml
RUN docker-php-ext-install filter
RUN apt-get install libzip-dev -y
RUN docker-php-ext-install zip
RUN docker-php-ext-install bcmath
RUN apt install libwebp-dev
RUN docker-php-ext-configure gd --with-freetype --with-jpeg --with-webp
RUN docker-php-ext-install gd
RUN docker-php-ext-install intl

Отлично у нас есть все RUN со всеми нужными нам модулями, библиотеками и зависимостями.

Наши слои готовы. Осталось добавить вишенку на торте. Это FROM, WORKDIR и CMD.

  1. FROM - какой базовый образ брать.
    FROM php:8.1.5-fpm

  2. WORKDIR - домашняя директория
    WORKDIR /var/www

  3. CMD - сервис, который должен быть запушен всегда.
    CMD ["php-fpm”]

Пункт 4. Перенос результата в Dockerfile.

Удаляем тестовый контейнер:

docker stop pensive_cray
pensive_cray
docker rm pensive_cray
pensive_cray

Переходим в директорию Dockerfile php-fpm:

cd /var/apps/domain_name/volumes/build/php-fpm8.1

Вставляем в Dockerfile php-fpm полученный результат.

mcedit Dockerfile
FROM php:8.1.5-fpm

WORKDIR /var/www

RUN apt update
RUN docker-php-ext-install exif
RUN apt-get install libmagickwand-dev libmagickcore-dev -y
RUN pecl install imagick
RUN docker-php-ext-enable imagick
RUN PHP_OPENSSL=yes
RUN docker-php-ext-install xml
RUN docker-php-ext-install filter
RUN apt-get install libzip-dev -y
RUN docker-php-ext-install zip
RUN docker-php-ext-install bcmath
RUN apt install libwebp-dev
RUN docker-php-ext-configure gd --with-freetype --with-jpeg --with-webp
RUN docker-php-ext-install gd
RUN docker-php-ext-install intl

CMD ["php-fpm"]

Далее пробуем запустить сборку контейнера по получившемуся Dockerfile:

docker build -f (путь до Dockerfile)

Если вы в директории, где находится Dockerfile, получается следующее:

docker -d build .

Если тестовая сборка завершилась без ошибок, значит ошибок при написание команд не обнаружено и вы написали все правильно!

/volumes/build/php-fpm# docker build .
Sending build context to Docker daemon   2.56kB
Step 1/18 : FROM php:8.1.5-fpm
 ---> 17bca48e4475
Step 2/18 : WORKDIR /var/www
 ---> Using cache
 ---> e5df181ecab6
Step 3/18 : RUN apt update
 ---> Using cache
 ---> 8b9514675b7d
Step 4/18 : RUN docker-php-ext-install exif
 ---> Using cache
 ---> 5558b4578bac
Step 5/18 : RUN apt-get install libmagickwand-dev libmagickcore-dev -y
 ---> Using cache
 ---> 3e4d8b2c9cf0
Step 6/18 : RUN pecl install imagick
 ---> Using cache
 ---> 2d001d41b213
Step 7/18 : RUN docker-php-ext-enable imagick
 ---> Using cache
 ---> a73532e75edd
Step 8/18 : RUN PHP_OPENSSL=yes
 ---> Using cache
 ---> b17d13a149c5
Step 9/18 : RUN docker-php-ext-install xml
 ---> Using cache
 ---> 1e7762060ed7
Step 10/18 : RUN docker-php-ext-install filter
 ---> Using cache
 ---> 361820f59b1c
Step 11/18 : RUN apt-get install libzip-dev -y
 ---> Using cache
 ---> 05dd631e40d2
Step 12/18 : RUN docker-php-ext-install zip
 ---> Using cache
 ---> ce67e77753d0
Step 13/18 : RUN docker-php-ext-install bcmath
 ---> Using cache
 ---> 931aa5e4650a
Step 14/18 : RUN apt install libwebp-dev
 ---> Using cache
 ---> 9bef1b459423
Step 15/18 : RUN docker-php-ext-configure gd --with-freetype --with-jpeg --with-webp
 ---> Using cache
 ---> 184d8ee067a0
Step 16/18 : RUN docker-php-ext-install gd
 ---> Using cache
 ---> 2fbc109397c0
Step 17/18 : RUN docker-php-ext-install intl
 ---> Using cache
 ---> 23bb5f7f91ef
Step 18/18 : CMD ["php-fpm"]
 ---> Using cache
 ---> d74294bc6db6
Successfully built d74294bc6db6

Теперь мы оптимизируем Dockerfile, чтобы не было много слоев. Сейчас их 18!

Разделим установки библиотек, модулей. Это упростить нам жизнь в будущем.

Берем команды установки библиотек:

RUN apt-get update
RUN apt-get install libmagickwand-dev libmagickcore-dev -y
RUN apt-get install libzip-dev -y
RUN apt install libwebp-dev

Объединим их в один слой с помощью обратного слеша \ (перенос на новую строку).

Получаем:

RUN apt-get update
RUN apt-get install -y \
    libmagickwand-dev \
    libmagickcore-dev \
    libzip-dev \
    libwebp-dev

Объедим команды apt-get update и apt-get install. Так как это команды, необходимо использовать and (&&).

Получается:

RUN apt-get update \
    && apt-get install -y \
    libmagickwand-dev \
    libmagickcore-dev \
    libzip-dev \
    libwebp-dev

Мы объединили библиотеки в один слой. В дальнейшем, если будут необходимы дополнительные библиотеки или пакеты мы можем вписывать их в этот слой.

Остались модули. У нас имеются команды:

RUN docker-php-ext-install exif
RUN docker-php-ext-enable imagick
RUN docker-php-ext-install xml
RUN docker-php-ext-install filter
RUN docker-php-ext-install zip
RUN docker-php-ext-install bcmath
RUN docker-php-ext-configure gd --with-freetype --with-jpeg --with-webp
RUN docker-php-ext-install gd
RUN docker-php-ext-install intl

Также объединяем их в один слой с помощью обратного слэша и (т.к это команды) and (&&).

Получается:

RUN docker-php-ext-install exif \
 && pecl install imagick \
 && docker-php-ext-enable imagick \
 && PHP_OPENSSL=yes \
 && docker-php-ext-install xml \
 && docker-php-ext-install filter \
 && docker-php-ext-install zip \
 && docker-php-ext-install bcmath \
 && docker-php-ext-configure gd --with-freetype --with-jpeg --with-webp \
 && docker-php-ext-install gd \
 && docker-php-ext-install intl

Тестируем:

@php:/var/apps/domain_name/volumes/build/php-fpm# docker build .
Sending build context to Docker daemon   2.56kB
Step 1/5 : FROM php:8.1.5-fpm
 ---> 17bca48e4475
Step 2/5 : WORKDIR /var/www
 ---> Using cache
 ---> e5df181ecab6
Step 3/5 : RUN apt-get update     && apt-get install -y     libmagickwand-dev     libmagickcore-dev     libzip-dev     libwebp-dev
 ---> Using cache
 ---> 54389f22f55f
Step 4/5 : RUN docker-php-ext-install exif  && pecl install imagick  && docker-php-ext-enable imagick  && PHP_OPENSSL=yes  && docker-php-ext-install xml  && docker-php-ext-install filter  && docker-php-ext-install zip  && docker-php-ext-install bcmath  && docker-php-ext-configure gd --with-freetype --with-jpeg --with-webp  && docker-php-ext-install gd  && docker-php-ext-install intl
 ---> Using cache
 ---> e54e458d6522
Step 5/5 : CMD ["php-fpm"]
 ---> Using cache
 ---> 534c59afa067
Successfully built 534c59afa067

Вместо 18 слоев получилось всего 5. Это отличный результат!

Dockerfile для php8.1-fpm готов.

Dockerfile mysql и nginx.

Так как во второй статье мы для каждого контейнера добавили Dockerfile, в mysql и nginx нам нужно добавить какой образ использовать. У нас нет необходимости ставить дополнительные библиотеки, модули в данные контейнеры на текущий момент. Поэтому добавляем в Dockerfile только FROM:

mysql:

FROM mysql:latest

nginx:

FROM nginx:latest

Запуск docker-compose.

Базовые ключи для запуска docker-compose, которые необходимо знать:

  1. up - поднимает контейнер с выводом в консоль.
    docker-compose up

  2. -d - поднимает контейнер без вывода в консоль.
    docker-compose up -d

  3. --force-recreate перечитывает конфигурацию docker-compose.yml и поднимает контейнер с учетом новых параметров в docker-compose.yml
    docker-compose up -d –-force-recreate

  4. --build перечитывает Dockerfile и поднимает контейнер с учетом новых параметров в Dockerfile и docker-compose.yml
    docker-compose up -d –-build

Очищаем все тестовые образы с помощью команды docker system prune --volumes --all.

Для запуска docker-compose необходимо находиться в директории, где лежит этот самый docker-compose.yml.

Переходим в директорию с docker-compose. 

cd /var/app/domain_name

Запускаем:

docker-compose up -d

После непродолжительного ожидания сборки образов, мы  получаем заветные:

Starting php-fpm ... done
Starting nginx   ... done
Starting mysql   ... done

Проверяем:

# docker ps
CONTAINER ID   IMAGE                 COMMAND                  CREATED          STATUS          PORTS                                                                      NAMES
47d63fac8e4f   domain_name_nginx     "/docker-entrypoint.…"   10 minutes ago   Up 13 seconds   0.0.0.0:80->80/tcp, :::80->80/tcp, 0.0.0.0:443->443/tcp, :::443->443/tcp   DOMAIN_NAME-nginx
941e858869e4   domain_name_php-fpm   "docker-php-entrypoi…"   10 minutes ago   Up 13 seconds   9000/tcp, 0.0.0.0:9000->9010/tcp, :::9000->9010/tcp                        DOMAIN_NAME-php-fpm
ce54ddd5fdd1   domain_name_mysql     "docker-entrypoint.s…"   10 minutes ago   Up 4 seconds    3306/tcp, 33060/tcp, 0.0.0.0:3310->3310/tcp, :::3310->3310/tcp             DOMAIN_NAME-mysql

Все контейнеры запущены и работают.

Что, если если у вас, вдруг, STATUS не UP? 

Пример:

STATUS
Restarting (1) Less than a second ago

Значит, контейнер не запущен. Скорее всего где то в конфигурационных файлах допущена ошибка.

Смотрим логи контейнера:

docker logs <ID или NAMES контейнера>

Исправляем ошибку и заново запускаем docker-compose.yml.

docker-compose restart

Нам осталось проксировать трафик с nginx в контейнер php-fpm. Для этого приводим конфигурационный файл DOMAIN_NAME.conf по пути ./volumes/etc/nginx/sites-enabled/DOMAIN_NAME.conf к такому виду:

server {

        listen   80;

        server_name DOMAIN_NAME.com;

        access_log /var/www/DOMAIN_NAME/log/nginx/access.log;

        error_log /var/www/DOMAIN_NAME/log/nginx/error.log;

        location ~ /\.(svn|git|hg) {

                deny all;

        }

        location ~* ^.+\.(css|jpg|jpeg|gif|png|ico|zip|tgz|gz|rar|bz2|doc|xls|pdf|ppt|txt|tar|mid|midi|wav|bmp|rtf|js|html|swf)$ {

                root /var/www/DOMAIN_NAME/data;

                expires max;

                access_log   off;

        }

        root /var/www/DOMAIN_NAME/data;

        index index.php index.html index.htm;

        location ~ \.php$ {

                fastcgi_pass 172.16.1.5:9010;

                fastcgi_index index.php;

                include fastcgi_params;

                fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;

        }

}

В /volumes/etc/php/fpm.pool.d/domain.conf

Указываем id пользователя и id группы из /etc/passwd. В нашем случае 1001 и 1001.

   user = 1001  
   group = 1001

Перезагружаем:

docker-compose restart

Обязательно проверьте, что все работает c помощью docker ps!

Все сервисы работают. Осталось только добавить в домашнюю директорию площадки код и создать базу данных в mysql.

Для создания БД необходимо зайти в контейнер mysql и там добавить пользователя.

Развернем код WordPress.

Переходим в /var/www/DOMAIN_NAME/.

cd /var/www/DOMAIN_NAME/

Скачиваем WordPress:

wget https://ru.wordpress.org/latest-ru_RU.zip

Распаковываем:

unzip latest-ru_RU.zip

Переносим все из директории wordpress/ в data/. Можно все сделать с помощью F6 в mc.

Присваиваем все файлы пользователю площадки.

chown -R DOMAIN_NAME: /var/www/DOMAIN_NAME/

Переходим на сайт в браузере:

Все работает.

Осталось указать ip адрес mysql, имя БД, пользователя и пароль.

И можно работать!

Итак, в этой статье мы с вами познакомились с написанием Dockerfile, запустили docker-compose и подняли все контейнеры с помощью одной команды. Для практики рекомендуем писать разные docker-compose экспериментировать с Dockerfile, а также пробовать ставить новые службы в контейнер. Ведь теория это одно, а практика - это совсем другое. 

Мы написали контейнеры для LEMP-проектов. Важно, что куда бы мы ни перенесли данные контейнеры, они везде будут работать одинаково. Данные yml можно загрузить в систему хранения репозиторием (например, в gitlab), после чего выгружать на новые сервера с помошью git. 

Всем спасибо за чтение серии статей по Docker. Надеемся, что эта информация была для вас познавательной, и она поможет вам в будущем стать высококвалифицированным специалистом. 

Если остались вопросы - задавайте в комментариях, мы с радостью на них ответим. Всем удачного администрирования и чтоб ваш PROD никогда не падал!

P.S: В следующей статье мы будем рассматривать решение для удаленного управления конфигурациями Ansible. А также напишем playbook для развертывание LEMP-сервера с использование docker. Поэтому не забывайте ставить лайки и подписываться на нас.
Больше интересного в нашем телеграм-канале DevOps FM.

Комментарии (1)


  1. webdevium
    29.04.2022 13:22
    +1

    Для установки PHP расширений внутри контейнера отлично подходит вот этот чудный инструмент.
    Рекомендую!