Docker - упрощение жизни разработчика
Сразу оговорюсь, на авторитетное мнение не претендую, сам начал недавно работать с Docker. И это моя первая серьезная заметка. Про установку Docker писать не буду, под каждую операционную систему установка отличается.
Небольшое предисловие…
Когда проект выходит за рамки простого сайта, начинается головная боль с деплоем, особенно если все крутится не только на php но и на nodejs и т.д. Вот и у меня так получилось, beckend на laravel, фронт на nuxtjs, админка отдельным приложением и на поддомене тоже на nuxtjs, так же redis, websocket сервер. Полный набор для кошмарных ночей при деплое =)))
Что же такое Docker и как он мне помог?
Docker это система контейнеризации — каждое приложение изолируется друг от друга и работает самостоятельно (в технические подробности вдаваться не буду, понять достаточно сложно).
Написав «шаблон» для Docker его можно развернуть на рабочем компьютере и на сервере абсолютно с одинаковыми настройками, тут мы снимаем большую головную боль даже на примере версии php, не надо постоянно ее проверять и менять.
Итак давайте напишем простой пример для Docker. Напишу как поднять nginx + php, если будет интересно могу написать заметку более углубленно (nginx-proxy + nginx + php + nodejs + mysql + redis + автоматическое получение ssl сертификата letsencrypt) + управление через Makefile =)))
Структура проекта:
Для начала напишем файл docker-compose.yml — в нем основные инструкции для запуска контейнеров
Что же тут происходит?
Мы создаем два Docker контейнера nginx и php, давайте разберем что за что отвечает.
Nginx:
image — подключаем готовый образ nginx версии 1.17 c docker hub
restart: always — в случае падения перезапускаем
ports — проброс портов (в контейнере порт 80 прокидываем наружу тоже на 80 порт)
volumes — самая сложная для понимания инструкция. Монтируем содержимое папки src внутрь контейнера в папку /usr/share/nginx/html и так же монтируем конфиг nginx
working_dir — рабочая папка внутри контейнера, что бы при заходе в контейнер сразу попадать в эту папку.
C php тоже самое только образ мы берем не с docker hub а собираем сами, поэтому вместо image мы используем build с сылкой на Dockerfile внутри папки php.
Dockerfile:
nginx.conf
Теперь можно запускать Docker командой
docker-compose up --build — билдим и можем смотреть за логами
docker-compose up --build -d — запускается в фоновом режиме
docker-compose stop — останавливаем
docker-compose ps или docker ps — список запущенных контейнеров
Так же хочу сказать что монтирование папок в Docker великолепная вещь! В папке src мы можем спокойно править код и все изменения увидим на сайте без пересборки контейнера
Статья получилась достаточно сложной для понимания, задавайте вопросы в комментариях.
П.С. В конфигах nginx не особо силен, если где ошибки прошу меня поправить.
Спасибо за внимание =)
Небольшое предисловие…
Когда проект выходит за рамки простого сайта, начинается головная боль с деплоем, особенно если все крутится не только на php но и на nodejs и т.д. Вот и у меня так получилось, beckend на laravel, фронт на nuxtjs, админка отдельным приложением и на поддомене тоже на nuxtjs, так же redis, websocket сервер. Полный набор для кошмарных ночей при деплое =)))
Что же такое Docker и как он мне помог?
Docker это система контейнеризации — каждое приложение изолируется друг от друга и работает самостоятельно (в технические подробности вдаваться не буду, понять достаточно сложно).
Написав «шаблон» для Docker его можно развернуть на рабочем компьютере и на сервере абсолютно с одинаковыми настройками, тут мы снимаем большую головную боль даже на примере версии php, не надо постоянно ее проверять и менять.
Итак давайте напишем простой пример для Docker. Напишу как поднять nginx + php, если будет интересно могу написать заметку более углубленно (nginx-proxy + nginx + php + nodejs + mysql + redis + автоматическое получение ssl сертификата letsencrypt) + управление через Makefile =)))
Структура проекта:
├── Docker
│ ├── nginx
│ │ ├── nginx.conf
│ │ └── ...
│ ├── php
│ │ ├── Dockerfile
│ │ └── ...
│ ├── src # Исходники приложения
│ ├── app
│ ├── bootstrap
│ ├── config
│ ├── artisan
│ └── ...
│ ├── docker-compose.yml
│ ├── README.md
│ └── ...Для начала напишем файл docker-compose.yml — в нем основные инструкции для запуска контейнеров
version: '3'
services:
nginx:
image: nginx:1.17
restart: always
ports:
- 80:80
volumes:
- ./src:/usr/share/nginx/html
- ./nginx/nginx.conf:/etc/nginx/nginx.conf
working_dir: /usr/share/nginx/html
php:
build: ./php
restart: always
volumes:
- ./src:/usr/share/nginx/html
working_dir: /usr/share/nginx/htmlЧто же тут происходит?
Мы создаем два Docker контейнера nginx и php, давайте разберем что за что отвечает.
Nginx:
image — подключаем готовый образ nginx версии 1.17 c docker hub
restart: always — в случае падения перезапускаем
ports — проброс портов (в контейнере порт 80 прокидываем наружу тоже на 80 порт)
volumes — самая сложная для понимания инструкция. Монтируем содержимое папки src внутрь контейнера в папку /usr/share/nginx/html и так же монтируем конфиг nginx
working_dir — рабочая папка внутри контейнера, что бы при заходе в контейнер сразу попадать в эту папку.
C php тоже самое только образ мы берем не с docker hub а собираем сами, поэтому вместо image мы используем build с сылкой на Dockerfile внутри папки php.
Dockerfile:
# Версия php, в нашем случае именно fpm
FROM php:7.3-fpm
# Устанавливаем расшерения
RUN apt-get update && apt-get install -y \
zip \
unzip\
supervisor \
curl \
wget \
git \
libxslt-dev \
libicu-dev \
libmcrypt-dev \
libwebp-dev \
libjpeg62-turbo-dev \
libpng-dev libxpm-dev \
libfreetype6-dev \
libzip-dev \
&& docker-php-ext-install -j$(nproc) iconv \
&& docker-php-ext-configure gd \
--with-gd \
--with-webp-dir \
--with-jpeg-dir \
--with-png-dir \
--with-zlib-dir \
--with-xpm-dir \
--with-freetype-dir \
--enable-gd-native-ttf \
&& docker-php-ext-install \
iconv \
gd \
mysqli \
pdo \
pdo_mysql \
mbstring \
tokenizer \
opcache \
exif \
zip \
pcntl
RUN pecl install redis \
&& pecl install xdebug \
&& pecl install mcrypt \
&& docker-php-ext-enable mcrypt \
&& docker-php-ext-enable redis xdebug
# устанавливаем compose, если нужно
RUN curl -sS https://getcomposer.org/installer | \
php -- --install-dir=/usr/bin/ --filename=composer
CMD ["php-fpm"]Отлично! php у нас работает, теперь необходимо связать php и nginx, и настроить nginx. Помните в docker-compose.yml мы монтировали настройки nginx? =)nginx.conf
worker_processes 1;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
map $sent_http_content_type $expires {
"text/html" epoch;
"text/html; charset=utf-8" epoch;
default off;
}
# backend server
server {
listen 80;
server_name localhost;
root /usr/share/nginx/html/public;
add_header X-Frame-Options "SAMEORIGIN";
add_header X-XSS-Protection "1; mode=block";
add_header X-Content-Type-Options "nosniff";
index index.html index.htm index.php;
charset utf-8;
client_max_body_size 32m;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location = /favicon.ico { access_log off; log_not_found off; }
location = /robots.txt { access_log off; log_not_found off; }
error_page 404 /index.php;
location ~ \.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 ~ /\.(?!well-known).* {
deny all;
}
}
}Теперь можно запускать Docker командой
docker-compose up --build — билдим и можем смотреть за логами
docker-compose up --build -d — запускается в фоновом режиме
docker-compose stop — останавливаем
docker-compose ps или docker ps — список запущенных контейнеров
Так же хочу сказать что монтирование папок в Docker великолепная вещь! В папке src мы можем спокойно править код и все изменения увидим на сайте без пересборки контейнера
Статья получилась достаточно сложной для понимания, задавайте вопросы в комментариях.
П.С. В конфигах nginx не особо силен, если где ошибки прошу меня поправить.
Спасибо за внимание =)
Комментарии: 14
Авторизуйтесь или зарегистрируйтесь, чтобы оставлять комментарии.
1. Вот вы создаете контейнер nginx на основании готового образа. Куда он устанавливается? В операционную систему которая не сервере? Или создается своя файловая система внутри докера? Вот к примеру указано что настройки сервера тут /etc/nginx/nginx.conf — это находится в операционной системе сервера? А как быть если до запуска вашего контейнера на сервере (машине) уже стоял сервер (nginx)? Вы затрете его конфигурационный файл?
2. Контейнер с php -вы пишите что мол мы не берем готовый а делаем сами по информации из докер файла в директории php. И в этом файле команды по установке (хотя и несколько искаженные как мне кажется, видимо это синтаксис такой докер файла.) Опять таки — куда устанавливается интерпретатор? В систему сервера? А что если там уже установлена своя версия языка, необходимая для других проектов?
3. Каким образом работает перенаправление запроса от пользователя в нужный контейнер? Ну тоесть докер более или менее — это виртуализация. Есть машина сервер с IP 2.2.2.2 Пользователь делает запрос на домен test.com, DNS сервер его отправляет на ваш сервер на порт 80. И как дальше то? К примеру у вас есть 5 контейнеров, в каждом из которых работает свой nginx и лежит свой сайт. А значит есть 5 директорий site-available (ну или как-то так), в которых должны лежать конфигурации для привязки домена к конкретной директории. Как и кто занимается разбором в каком из запущенных контейнеров лежит тот сайт, который запросил пользователь?
4. Правильно я понимаю, что если работать с докер контейнерами, в которых живут сайты(проекты), то все администрирование сервера нужно вести исключительно без применения каких либо визуальных панелей и интерфейсов. Что я имею ввиду. У меня есть сервер выделенный с установленой там убунтой, apache, php и с бесплатной панелью vesta. Через панель я могу создавать новые www домены, для которых автоматом создается директория и конфигурационный файл. Могу работать с базой данных и так далее. Но все это бессмысленно, если на сервере запущено 5 разных nginx, 5 разных, баз данных и так далее, панель это все просто не увидит.
Ну и еще конечно куча вопросов рождаются в голове, но пока хватит)Спасибо.
1) Каждый контейнер изолирован друг от друга и внутри контейнера своя файловая система, внутрь контейнера мы можем монтировать папки через volume. Именно внутрь контейнера, а не внутрь файловой системы сервера.
2) Как говорил выше, контейнеры изолированы. В моем примере nginx связан с php через fastcgi
3) Этот вопрос достаточно сложный, сам долго искал решение, т.к. у меня: api сервер на ларавель, 2 отдельных приложения на nuxtjs и вебсокет сервер и это все на разных поддоменах. Домен и поддомены через А запись направлены на ип сервера и разруливается nginx-proxy с достаточно простым синтаксисом
4) На самом деле все намного проще ))) Если будет интересно напишу более углубленную статью, в ней расскажу как поднять nginx-proxy + получение автоматом ссл сертификата, в этой связке разворачивание нового сайта сводится к клону гитхаба и запуска контейнера.