Dockerfile: создать образ с Nginx и PHP‑FPM на Ubuntu 16.04

Введение
Docker — это виртуализация на уровне ОС, ориентированная на разработчиков и системных администраторов. Docker упрощает создание и развёртывание приложений в изолированной среде. Dockerfile — это скрипт с набором инструкций, которые выполняются последовательно при сборке Docker‑образа.
В этом пошаговом руководстве вы научитесь создавать собственный образ на базе Ubuntu 16.04 с Nginx, PHP‑FPM 7 и Supervisord. Я объясню каждую секцию Dockerfile и сопутствующие файлы, а также дам советы по безопасности, отладке и альтернативные подходы.
Краткие определения:
- Dockerfile: файл с инструкциями для сборки образа.
- Образ (image): статичная, переносимая версия файловой системы, из которой запускают контейнер.
- Контейнер: запущенный экземпляр образа.
Требования
- Сервер с Linux (в примерах использованы команды для Ubuntu). Можно работать локально или на удалённом хосте.
- Привилегии root или sudo.
- Установленный Docker или доступ для установки (в шаге 1 показана установка через apt).
Важно: в примере используется Ubuntu 16.04 как базовый образ. Учтите, что это довольно старая версия ОС — при разработке на продакшн рекомендовано рассмотреть более новые LTS‑версии Ubuntu (например, 18.04/20.04/22.04) или официальные минимальные образы.
Команды Dockerfile — быстрый обзор
Ниже — основные инструкции Dockerfile с кратким объяснением:
- FROM — базовый образ; должен быть первой инструкцией (за исключением комментариев).
- MAINTAINER — необязательная метаинформация с автором/поддерживающим.
- RUN — выполнить команду при сборке образа.
- COPY / ADD — добавить файлы из контекста сборки в образ; ADD умеет распаковывать архивы и скачивать по URL.
- ENV — задать переменные окружения.
- CMD — команда по умолчанию, выполняемая при запуске контейнера (можно переопределить docker run).
- ENTRYPOINT — фиксирует исполняемый процесс контейнера; CMD дополняет ENTRYPOINT.
- WORKDIR — рабочая директория для последующих команд.
- USER — поменять пользователя внутри контейнера.
- VOLUME — объявить точки монтирования для внешних томов.
- EXPOSE — декларация открытых портов (не пробрасывает порты автоматически).
Шаг 1 — Установка Docker на сервере
Подключитесь к серверу и обновите список пакетов:
ssh [email protected]
apt-get updateУстановите docker.io через apt:
apt-get install docker.ioЗапустите сервис Docker и включите автозапуск при старте системы:
systemctl start docker
systemctl enable dockerПосле этого Docker доступен и готов к использованию.
Шаг 2 — Создаём директорию и Dockerfile
Создадим папку для образа и пустой Dockerfile:
mkdir ~/myimages
cd myimages/
touch DockerfileВ этом примере мы установим Nginx, PHP‑FPM 7 и Supervisord в образ на базе Ubuntu 16.04. Supervisord позволяет запускать и контролировать несколько сервисов в одном контейнере.
Откройте Dockerfile в редакторе (в примере использован nano):
nano DockerfileДобавьте в начало базовый образ:
#Download base image ubuntu 16.04
FROM ubuntu:16.04Обновим index пакетов внутри образа:
# Update Ubuntu Software repository
RUN apt-get updateУстановим nginx, php7.0-fpm и supervisor, а затем очистим кеш apt, чтобы уменьшить размер слоя образа:
# Install nginx, php-fpm and supervisord from ubuntu repository
RUN apt-get install -y nginx php7.0-fpm supervisor && \
rm -rf /var/lib/apt/lists/*Далее задаём переменные окружения, чтобы удобнее ссылаться на пути в конфигурациях, и включим правильную настройку php.ini и nginx:
#Define the ENV variable
ENV nginx_vhost /etc/nginx/sites-available/default
ENV php_conf /etc/php/7.0/fpm/php.ini
ENV nginx_conf /etc/nginx/nginx.conf
ENV supervisor_conf /etc/supervisor/supervisord.conf
# Enable php-fpm on nginx virtualhost configuration
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:
#Copy supervisor configuration
COPY supervisord.conf ${supervisor_conf}Создадим runtime каталог для PHP‑FPM и назначим владельцем www‑data, чтобы веб‑сервер имел права на каталог /var/www/html:
RUN mkdir -p /run/php && \
chown -R www-data:www-data /var/www/html && \
chown -R www-data:www-data /run/phpОбъявим VOLUME, чтобы можно было монтировать специфичные папки с хоста:
# Volume configuration
VOLUME ["/etc/nginx/sites-enabled", "/etc/nginx/certs", "/etc/nginx/conf.d", "/var/log/nginx", "/var/www/html"]Скопируем скрипт старта и зададим команду по умолчанию, а также откроем порты HTTP/HTTPS:
# Configure Services and Port
COPY start.sh /start.sh
CMD ["./start.sh"]
EXPOSE 80 443Сохраняем Dockerfile. Ниже — полный файл целиком (сохраните в проекте как Dockerfile):
#Download base image ubuntu 16.04
FROM ubuntu:16.04
# Update Software repository
RUN apt-get update
# Install nginx, php-fpm and supervisord from ubuntu repository
RUN apt-get install -y nginx php7.0-fpm supervisor && \
rm -rf /var/lib/apt/lists/*
#Define the ENV variable
ENV nginx_vhost /etc/nginx/sites-available/default
ENV php_conf /etc/php/7.0/fpm/php.ini
ENV nginx_conf /etc/nginx/nginx.conf
ENV supervisor_conf /etc/supervisor/supervisord.conf
# Enable php-fpm on nginx virtualhost configuration
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}
#Copy supervisor configuration
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 configuration
VOLUME ["/etc/nginx/sites-enabled", "/etc/nginx/certs", "/etc/nginx/conf.d", "/var/log/nginx", "/var/www/html"]
# Configure Services and Port
COPY start.sh /start.sh
CMD ["./start.sh"]
EXPOSE 80 443Конфигурационные файлы: default, supervisord.conf и start.sh
В той же директории создайте три файла: default (виртуальный хост nginx), supervisord.conf и start.sh.
Создаём файл default:
vim defaultВставьте конфигурацию виртуального хоста:
server {
listen 80 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.0-fpm.sock;
}
# deny access to .htaccess files, if Apache's document root
# concurs with nginx's one
#
#location ~ /\.ht {
# deny all;
#}
}Создаём supervisord.conf:
vim supervisord.confВставьте содержимое:
[unix_http_server]
file=/dev/shm/supervisor.sock ; (the path to the socket file)
[supervisord]
logfile=/var/log/supervisord.log ; (main log file;default $CWD/supervisord.log)
logfile_maxbytes=50MB ; (max main logfile bytes b4 rotation;default 50MB)
logfile_backups=10 ; (num of main logfile rotation backups;default 10)
loglevel=info ; (log level;default info; others: debug,warn,trace)
pidfile=/tmp/supervisord.pid ; (supervisord pidfile;default supervisord.pid)
nodaemon=false ; (start in foreground if true;default false)
minfds=1024 ; (min. avail startup file descriptors;default 1024)
minprocs=200 ; (min. avail process descriptors;default 200)
user=root
; the below section must remain in the config file for RPC
; (supervisorctl/web interface) to work, additional interfaces may be
; added by defining them in separate rpcinterface: sections
[rpcinterface:supervisor]
supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface
[supervisorctl]
serverurl=unix:///dev/shm/supervisor.sock ; use a unix:// URL for a unix socket
[include]
files = /etc/supervisor/conf.d/*.conf
[program:php-fpm7.0]
command=/usr/sbin/php-fpm7.0 -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 +x start.shВажно: проверяйте пути бинарников в образе (nginx, php-fpm, supervisord). В разных дистрибутивах они могут отличаться.

Шаг 3 — Сборка образа и запуск контейнера
В директории с Dockerfile и файлами конфигурации выполните:
docker build -t nginx_image .Проверьте, что образ создан:
docker imagesПеред запуском контейнера создайте директорию для webroot на хосте:
mkdir -p /webrootЗапустите контейнер, смонтировав /webroot в /var/www/html и открыв порт 80:
docker run -d -v /webroot:/var/www/html -p 80:80 --name hakase nginx_imageПроверим, что контейнер работает:
docker psПримечание по параметрам команд:
- –name hakase nginx_image — контейнер с именем hakase, созданный на основе образа nginx_image.
- -p 80:80 — проброс порта 80 на хосте в порт 80 контейнера.
- -v /webroot:/var/www/html — монтирование папки с хоста в контейнер (содержимое /webroot будет доступно как /var/www/html).
Если контейнер запущен без ошибок, переходим к тестированию.
Шаг 4 — Тестирование Nginx и PHP‑FPM
Создадим простой HTML-файл в /webroot на хосте:
echo 'Nginx and PHP-FPM 7 inside Docker Container
' > /webroot/index.htmlПроверим доступ командой curl (замените IP на IP вашего хоста):
curl 192.168.1.250
curl -I 192.168.1.250Ожидаемый результат — HTML‑страница или заголовки ответа от Nginx.

Для проверки PHP создадим phpinfo:
echo '' > /webroot/info.phpОткройте в браузере:
http://
Вы увидите страницу phpinfo(), подтверждающую работу PHP‑FPM через Nginx.

Если всё работает — образ nginx_image успешно собран и контейнер функционирует.
Полезные практики и проверочные списки
Краткая методология (микро‑SOP) для повторяемой сборки:
- Подготовить директорию проекта с Dockerfile и конфигурациями.
- Проверить пути и версии бинарников (nginx, php-fpm, supervisord).
- Собирать образ локально в чистом окружении (docker build).
- Тестировать контейнер с пробросом портов и монтированием локального каталога.
- Скриптировать тесты (curl, проверка процессов через docker exec).
- Произвести скан образа (clair, trivy) и зафиксировать результаты.
Стендовые критерии приёмки:
- Образ собирается без ошибок при docker build.
- Контейнер стартует и в supervisord запущены процессы nginx и php-fpm.
- Страница /index.html отдается корректно.
- /info.php отображает phpinfo() при включенной обработке .php.
Роль‑ориентированные чек-листы:
- Для разработчика:
- Монтирование /var/www/html должно отображать изменения в коде сразу.
- Наличие удобного логирования (stdout/stderr) или маппинг /var/log/nginx.
- Для системного администратора:
- Настроить мониторинг контейнера (ресурсы, перезапуски).
- Настроить хранение логов вне контейнера.
- Для инженера по безопасности:
- Минимизировать права процесса; избегать запуска сервисов от root.
- Просканировать образ на уязвимости.
Безопасность и hardening (рекомендации)
- Не запускайте сервисы под root внутри контейнера, если это возможно. Используйте USER www-data для запуска nginx/php‑fpm или создайте специализированного пользователя.
- Зафиксируйте версии пакетов в Dockerfile (apt-get install пакет=версия) для повторяемости сборки.
- Избегайте выполнения apt-get upgrade в Dockerfile — это усложняет контроль слоёв и воспроизводимость.
- Ограничьте доступность метаданных и сокетов: не монтируйте лишние хостовые сокеты в контейнер.
- Запустите сканирование образа инструментами типа trivy или clair перед продакшн‑развёртыванием.
- Минимизируйте размер образа: рассматривайте использование более лёгких базовых образов (alpine, debian:slim) и multi‑stage сборки.
Когда этот подход не подходит (контрпримеры)
- Если вы хотите разворачивать масштабируемый набор микросервисов с отдельными процессами для каждого сервиса, запуск нескольких демонов в одном контейнере (через Supervisord) нарушает принцип «один процесс — один контейнер». В таких случаях рекомендуется запускать nginx и php‑fpm в отдельных контейнерах и связать их через сеть Docker или docker‑compose.
- Если вам критична безопасность и минимальный вектор атаки, лучше использовать минимальные официальные образы, а не полный Ubuntu с apt.
Альтернативные подходы
- Docker Compose: описать сервисы nginx и php‑fpm как отдельные сервисы в docker‑compose.yml и запускать их вместе с docker-compose up —d. Это улучшит масштабируемость и управление.
- Официальные образы: использовать официальные образы nginx и php:fpm и настроить их взаимодействие — это уменьшит объем собственных конфигураций и облегчит обновления.
- Multi‑stage builds: полезно при сборке приложений, где сборочные зависимости можно убрать в финальный слой.
Совместимость и миграция
- Ubuntu 16.04 — относительно старая база; при подготовке к долгосрочной эксплуатации рассмотрите переход на более новые LTS‑релизы или официальные образы PHP/Nginx.
- Версии PHP и путей к сокетам (php7.0, /run/php/php7.0-fpm.sock) зависят от дистрибутива и версии PHP. При миграции на PHP 7.2+ обновите пути и имена пакетов.
Отладка — набор команд
- Просмотреть логи контейнера:
docker logs hakase- Выполнить команду внутри контейнера для диагностики:
docker exec -it hakase /bin/bash
ps aux | grep nginx
cat /var/log/nginx/error.log- Проверить, что сокет PHP‑FPM существует:
ls -l /run/phpШаблоны и сниппеты (cheat sheet)
- Быстрая сборка и запуск в одной строке (локально):
docker build -t nginx_image . && docker run -d -v $(pwd)/webroot:/var/www/html -p 80:80 --name hakase nginx_image- Остановить и удалить контейнер + образ:
docker stop hakase && docker rm hakase && docker rmi nginx_imageКраткое резюме
- Вы написали Dockerfile, установили Nginx, PHP‑FPM и Supervisord, подготовили конфигурации и проверили работу контейнера.
- Для продакшн‑среды рассмотрите разделение процессов по контейнерам, улучшение безопасности, фиксацию версий и сканирование образов.
Ссылки для справки:
- https://docs.docker.com/engine/reference/builder/
- https://github.com/ngineered/nginx-php-fpm
- https://github.com/docker-library/wordpress/
Важно: постоянно проверяйте совместимость версий и обновляйте базовые образы, когда это требуется.
Итоговые ключевые шаги
- Подготовка файлов (Dockerfile, default, supervisord.conf, start.sh).
- Сборка образа: docker build -t nginx_image .
- Запуск контейнера: docker run -d -v /webroot:/var/www/html -p 80:80 –name hakase nginx_image
- Тестирование: curl и просмотр phpinfo().
Похожие материалы
Несколько аккаунтов Skype: Multi Skype Launcher
Журнал для работы: повысить продуктивность
Персональные звуки уведомлений на Android
Скачивание шоу Hulu для офлайн‑просмотра
Microsoft Start: персонализированная новостная лента