Docker, часть 3 – создание образов при помощи Dockerfile

В предыдущей части данного руководства мы увидели, как можно сохранить изменения в контейнере в новый образ. Такой способ подходит, если количество изменений относительно невелико – вводить все команды вручную каждый раз может быть затруднительно. Для упрощения процесса сборки можно воспользоваться Dockerfile. Это специальный скрипт, в котором содержатся команды и инструкции, которые будут в заданной последовательности выполнены для сборки нового образа Docker.
В данном руководстве мы рассмотрим создание собственного образа Docker при помощи Dockerfile. Он будет подробно разобран, чтобы в дальнейшем вы легко смогли создать свой собственный скрипт.

Обзор команд Dockerfile

Dockerfile – это скрипт, содержащий набор команд dockerfile и операционной системы (то есть команд Linux). Прежде чем создать свой dockerfile, давайте познакомимся с этими командами. Вот наиболее важные из них:
FROM — Указывает базовый образ для создания нового образа. Эта команда должна быть первой в dockerfile.
MAINTAINER — Необязательная команда, указывает имя владельца образа.
RUN — Используется для выполнения команды в ходе сборки образа.
ADD — Скопировать файл из файловой системы хоста в новый образ. Можно указать URL файла, в этом случае Docker загрузит его в заданную директорию.
ENV — Определяет переменную среды.
CMD — Команда которая будет запущена при создании нового контейнера на основе образа.
ENTRYPOINT — Задает команду по умолчанию, которая будет выполнена при запуске контейнера.
WORKDIR — рабочий каталог для выполнения команды CMD.
USER — Задает пользователя или UID для создаваемого на основе образа контейнера.
VOLUME — Монтирует директорию хоста в контейнер.
EXPOSE — Указывает какие порты будут слушаться в контейнере.

На первый взгляд команды CMD и ENTRYPOINT кажутся одинаковыми. Они выполняют команду при запуске контейнера. Но все таки между ними есть разница. Мы не будем вдаваться в тонкости, запомните только то что если вы укажете CMD то докер выполнит эту команду, используя стандартную команду ENTRYPOINT, которая является /bin/sh -c. И эту команду вы сможете переопределить при запуске контейнера Если вы укажете ENTRYPOINT то при запуске контейнера переопределить команду вы уже не сможете.

Создание Dockerfile

На данном этапе мы создадим для Dockerfile новую директорию и определим, что мы хотим сделать при помощи Dockerfile.
Создайте новую директорию и пустой файл в ней

mkdir ~/myimages
cd myimages/
touch Dockerfile

Затем определим, какой образ требуется создать. В данном руководстве мы установим Nginx и PHP-FPM7, используя образ Ubuntu 18.04. Кроме того, нам потребуется Supervisord, чтобы запустить Nginx и PHP-FPM 7 одной командой.
Откройте Dockerfile в любом текстовом редакторе, например vim:

vim Dockerfile

В начале файла добавьте строку с указанием базового образа, который мы будем использовать (Ubuntu 18.04):

#Загрузить базовый образ Ubuntu 18.04
FROM ubuntu:18.04

Обновим программный репозиторий Ubuntu внутри Dockerfile при помощи команды ‘RUN‘.

#Обновить программный репозиторий Ubuntu
RUN apt-get update

Теперь установим приложения, который требуются для нашего образа. При помощи apt можно установить Nginx, PHP-FPM и Supervisord из репозитория Ubuntu. Добавьте соответствующую команду RUN:

#Установить nginx, php-fpm и supervisord
RUN apt-get install -y nginx php7.2-fpm supervisor && \
rm -rf /var/lib/apt/lists/*

После установки приложений их нужно настроить. Мы настроим Nginx для работы с PHP путем изменения конфигурации виртуального хоста по умолчанию. Можно отредактировать существующий файл конфигурации командой sed или заменить его новым файлом при помощи команды Dockerfile COPY.

#Определение переменных среды
ENV nginx_vhost /etc/nginx/sites-available/default
ENV php_conf /etc/php/7.2/fpm/php.ini
ENV nginx_conf /etc/nginx/nginx.conf
ENV supervisor_conf /etc/supervisor/supervisord.conf
#Конфигугация виртуального хоста nginx для работы с php-fpm
COPY default ${nginx_vhost}
RUN sed -i -e 's/;cgi.fix_pathinfo=1/cgi.fix_pathinfo=0/g' ${php_conf} && \
echo "\ndaemon off;" >> ${nginx_conf}

Теперь настроим Supervisord для Nginx and PHP-FPM, точно так же заменив файл конфигурации по умолчанию новым файлом, используя команду COPY.

#Копирование конфигурации supervisor
COPY supervisord.conf ${supervisor_conf}

Создадим новую директорию для sock-файла php-fpm и изменим владельца директории /var/www/html и директории PHP на www-data.

RUN mkdir -p /run/php && \
chown -R www-data:www-data /var/www/html && \
chown -R www-data:www-data /run/php

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

#Конфигурация тома
VOLUME ["/etc/nginx/sites-enabled", "/etc/nginx/certs", "/etc/nginx/conf.d", "/var/log/nginx", "/var/www/html"]

Наконец, нужно установить команду по умолчанию при запуске контейнера и открыть порты для HTTP и HTTPS. Для заданной ‘CMD’ команды по умолчанию мы создадим новый файл

start.sh, содержащий команду «supervisord», и скопируем его в новый образ командой ‘COPY‘.

#Настройка сервисов и портов
COPY start.sh /start.sh
CMD ["./start.sh"]

Указываем порты для nginx

#Порты для nginx
EXPOSE 80 443

Сохраните и закройте файл.

Вот весь скрипт Dockerfile целиком:

#Загрузить базовый образ Ubuntu 18.04
FROM ubuntu:18.04

#Обновить программный репозиторий Ubuntu
RUN apt-get update

#Установить nginx, php-fpm и supervisord
RUN apt-get install -y nginx php7.2-fpm supervisor && \
rm -rf /var/lib/apt/lists/*

#Определение переменных среды
ENV nginx_vhost /etc/nginx/sites-available/default
ENV php_conf /etc/php/7.2/fpm/php.ini
ENV nginx_conf /etc/nginx/nginx.conf
ENV supervisor_conf /etc/supervisor/supervisord.conf

#Конфигугация виртуального хоста nginx для работы с php-fpm
COPY default ${nginx_vhost}
RUN sed -i -e 's/;cgi.fix_pathinfo=1/cgi.fix_pathinfo=0/g' ${php_conf} && \
echo "\ndaemon off;" >> ${nginx_conf}

#Копирование конфигурации supervisor
COPY supervisord.conf ${supervisor_conf}

RUN mkdir -p /run/php && \
chown -R www-data:www-data /var/www/html && \
chown -R www-data:www-data /run/php

#Конфигурация тома
VOLUME ["/etc/nginx/sites-enabled", "/etc/nginx/certs", "/etc/nginx/conf.d", "/var/log/nginx", "/var/www/html"]

#Настройка сервисов и портов
COPY start.sh /start.sh
CMD ["./start.sh"]

#Порты для nginx
EXPOSE 80 443

Теперь внутри директории с Dockerfile создайте новый файл конфигурации виртуального хоста под названием «default», файл конфигурации supervisord «supervisord.conf» и скрипт конфигурации сервисов «start.sh».

vim default

Вставьте в файл конфигурации виртуального хоста следующий код:

server {
listen 80 default_server;
root /var/www/html;
index index.html index.htm index.nginx-debian.html;
server_name _;
location / {
try_files $uri $uri/ =404;
}
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/run/php/php7.2-fpm.sock;
}
# запретить доступ к файлам .htaccess, если корень документов Apache
# конфликтует с корнем документов nginx
#
# location ~ /\.ht {
# deny all;
#}
}

Откройте файл конфигурации Supervisord:

vim supervisord.conf

Вставьте следующий код конфигурации:

[unix_http_server]
file=/dev/shm/supervisor.sock ; (путь к файлу сокета)

[supervisord]
logfile=/var/log/supervisord.log ; (основной файл лога;по умолчанию $CWD/supervisord.log)
logfile_maxbytes=50MB ; (максимальный размер основного файла лога до ротации; по умолчанию 50MB)
logfile_backups=10 ; (количество резервных копий при ротации основного файла лога;по умолчанию 10)
loglevel=info ; (уровень сообщений лога;по умолчанию info (информационные); другие: debug,warn,trace – отладка, предупреждение, вся информация)
pidfile=/tmp/supervisord.pid ; (pid-файл supervisord;по умолчанию supervisord.pid)
nodaemon=false ; (запуск не в фоновом режиме, если true;по умолчанию false)
minfds=1024 ; (минимальное количество дескрипторов файлов запуска;по умолчанию 1024)
minprocs=200 ; (минимальное количество дескрипторов процессов;по умолчанию 200)
user=root ;

; приведенный ниже раздел должен оставаться в файле конфигурации, чтобы работал удаленный вызов процедур
; (supervisorctl/веб-интерфейс), можно добавить дополнительные интерфейсы, определив их
; в отдельных разделах rpcinterface:

[rpcinterface:supervisor]
supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface

[supervisorctl]
serverurl=unix:///dev/shm/supervisor.sock ; для UNIX-сокета используйте формат unix:// URL

; В разделе [include] может содержаться только параметр "files".
; В нем может быть приведен список нескольких файлов (разделенных пробелами или
; символами начала строки). Кроме того, он может содержать маски. Имена файлов
; интерпретируются относительно этого файла. Включенные файлы НЕ МОГУТ
; включать какие-то файлы сами.

[include]
files = /etc/supervisor/conf.d/*.conf

[program:php-fpm7.2]
command=/usr/sbin/php-fpm7.2 -F
numprocs=1
autostart=true
autorestart=true

[program:nginx]
command=/usr/sbin/nginx
numprocs=1
autostart=true
autorestart=true

Откройте файл start.sh.

vim start.sh

Вставьте следующие параметры конфигурации:

#!/bin/sh
/usr/bin/supervisord -n -c /etc/supervisor/supervisord.conf

Сохраните и закройте файл.

При помощи команды chmod сделайте файл start.sh исполняемым:

chmod +x start.sh

Создание нового образа и контейнера

Теперь, когда у нас есть все необходимые файлы конфигурации, можно собрать новый образ Docker на основе Ubuntu 18.04, используя наш Dockerfile. Для этого нужно выполнить следующую команду Docker:

docker build -t nginx_image .

Обратите внимание на точку, если вы находитесь в каталоге в котором создан Dockerfile. Если вы находитесь не в корне каталога, то вместо точки укажите директорию с докфайлом.  Если создание образа прошло без ошибок вы должны увидеть примерно следующее

.........

---> b0e31aed27a4
Removing intermediate container 5e610e002c60
Step 12/14 : VOLUME /etc/nginx/sites-enabled /etc/nginx/certs /etc/nginx/conf.d /var/log/nginx /var/www/html
---> Running in 1ad1d4030221
---> 2dd234e209ba
Removing intermediate container 1ad1d4030221
Step 13/14 : COPY start.sh /start.sh
---> 55bf3c632539
Removing intermediate container 61bec9b748b9
Step 14/14 : CMD ./start.sh
---> Running in d7a0eff0a3ee
---> e7e5dc3d6cd1
Removing intermediate container d7a0eff0a3ee
Successfully built e7e5dc3d6cd1

Successfully built e7e5dc3d6cd1, говорит о том что образ создан. После успешного выполнения команды можно проверить наличие нового образа при помощи команды images:

docker images

Попробуем создать на основе этого образа новый контейнер. Предварительно создадим на хосте новую директорию для данных корня документов:

mkdir -p /webroot

Запустим новый контейнер командой run:

docker run -d -v /webroot:/var/www/html -p 80:80 --name my_container nginx_image

И командой ps проверим, запустился ли новый контейнер под названием my_container:

docker ps

Разберем команду run более подробно:

—name my_container nginx_image — на основе образа «nginx_images» создаем новый контейнер с именем «my_container».
-p 80:80 — контейнер запускаетcя на 80 порте хоста.
-v /webroot:/var/www/html — содержимое директории хоста /webroot перезаписывает директорию /var/www/html в контейнере.
Новый контейнер на основе образа nginx_image должен работать без ошибок.

Тестирование работы Nginx и PHP-FPM в контейнере

Командой echo создайте в директории /webroot новый файл index.html:

echo '<h1>Nginx and PHP-FPM 7 inside Docker Container</h1>' > /webroot/index.html

Тестирование при помощи доступа к IP-адресу хоста командой curl (замените 192.168.1.5 на свой IP-адрес):
curl 192.168.1.5
curl -I 192.168.1.5

Теперь проверим, что PHP-FPM 7.2 работает – создадим в директории /webroot новый файл c phpinfo.

echo '<?php phpinfo(); ?>' > /webroot/info.php

Откройте веб-браузер и введите IP-адрес хоста:

http://192.168.1.5/info.php

Если все работает правильно, вы увидите следующий результат:

Заключение

Мы успешно создали новый образ и теперь можем создавать на его основе новые контейнеры. Более подробную информацию о создании образов и Dockerfile можно получить в документации Docker.

Если вы нашли ошибку, пожалуйста, выделите фрагмент текста и нажмите Ctrl+Enter.

Понравилась статья? Поделиться с друзьями:
Comments: 1
  1. Владимир

    Контейнер после создания тут же закрывается

Добавить комментарий

;-) :| :x :twisted: :smile: :shock: :sad: :roll: :razz: :oops: :o :mrgreen: :lol: :idea: :grin: :evil: :cry: :cool: :arrow: :???: :?: :!:

ИТ Проффи

Сообщить об опечатке

Текст, который будет отправлен нашим редакторам: