Очередная статья про Docker для новичка [nginx + php-fpm + postgresql + mongodb]

от автора

image

Всем доброго времени суток. Вдохновленный целым набором статей на тему поднятия окружения на докере, я решил поделиться своим опытом по данному вопросу.

Сразу оговорюсь, эта статья так сказать «от новичка новичку», поэтому постараюсь подробно рассказать обо всех сложностях и вопросах, которые у меня возникли в процессе настройки окружения в Docker.

Добро пожаловать под кат!

Итак, все что я опишу ниже, я буду делать на ноутбуке известной «фруктовой компании», но так как ранее я делал тоже самое на VDS под управлением Centos 7, то я буду делать небольшие лирические отступления с описание, как я это делал на VDS.

Начнем мы естественно в регистрации на docker hub, который будет выступать в качестве системы контроля версий, но только для наших контейнеров. Docker hub при бесплатном использовании позволяет иметь только 1 приватный репозиторий, поэтому мы будем каждый отдельный образ помечать соответствующими тегами — nginx, php7-fpm. Я не буду описывать создание репозитория, думаю, ни у кого с этим проблем не возникнет.

Теперь мы можем установить сам docker на нашу рабочую станцию — в моем случае это описание находится здесь.

При установке Docker на Mac у нас сразу устанавливается docker toolbox, в котором есть необходимый нам инструмент docker-compose. Мы будем использовать его для объединения наших контейнеров о общее окружение.

Установка docker-compose на Centos 7

К сожалению, на VDS мне пришлось устанавливать его отдельно через pip.

yum -y install python-pip pip install docker-compose

Далее логинимся в нашем Докере:

docker login

Теперь нам доступны наши приватные репозитории (правда там пока пусто), там правда сейчас пусто, но мы это скоро исправим:)

Для своего проекта я сделал следующую структуру файлов:

├── contaners                    # Директория с кастомными образами для docker │   ├── fpm │   │   ├── Dockerfile │   │   └── conf │   │       └── fpm.conf        # Необходимые настройки fpm, у меня файл пустой:) │   └── nginx │       ├── Dockerfile │       └── conf │           └── nginx.conf ├── database                     # Директоря для хранения баз данных ├── docker-compose.yml ├── logs                         # Директоря для хранения логов └── php-code                     # Директоря с php кодом     ├── html     └── index.php

Зачем нужна php-code/html

При отсутствии директории html образ контейнера nginx не запуститься, где-то я находил, что проблема решается указанием WORKDIR в Dockerfile, но эта директория все-равно понадобится.

Для проекта я буду использовать кастомные образы для nginx и fpm, поэтому их я вынес в отдельные директории. Кастомные образы описываются при помощи Dockerfile. Вот мои:

./contaners/fpm/Dockerfile

FROM php:fpm MAINTAINER nickname <my-email@domain>  RUN apt-get update && apt-get install -y \         libmcrypt-dev \         && apt-get install -y libpq-dev \         && docker-php-ext-install -j$(nproc) mcrypt \         && pecl install mongodb         && docker-php-ext-enable mongodb RUN docker-php-ext-install mbstring RUN docker-php-ext-install exif RUN docker-php-ext-install opcache  RUN docker-php-ext-configure pgsql -with-pgsql=/usr/local/pgsql \     && docker-php-ext-install pgsql pdo_pgsql COPY conf/ /usr/local/etc/php-fpm.d/ CMD ["php-fpm"]

./contaners/nginx/Dockerfile

 FROM nginx:latest MAINTAINER nickname <my-email@domain> COPY ./conf /etc/nginx/conf.d/

./contaners/nginx/conf/nginx.conf

server {     listen 80;     index index.php index.html;     server_name localhost;     error_log  /etc/logs/nginx/nginx_error.log;     access_log /etc/logs/nginx/nginx_access.log;     root /var/www;     location ~ \.php$ {         try_files $uri =404;         fastcgi_split_path_info ^(.+\.php)(/.+)$;         fastcgi_pass fpm:9000;         fastcgi_index index.php;         include fastcgi_params;         fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;         fastcgi_param PATH_INFO $fastcgi_path_info;     } } 

Установка расширений для PHP в докере делается черезвычайно просто:

docker-php-ext-install

или

docker-php-ext-enable  # в случае, если расширение уже установлено (как у меня через pecl)

Вся подготовительная работа проведена проведена, теперь надо описать как наши контейнеры будут взаимодействовать. Как я уже писал, делать это мы будем через docker-compose и правила взаимодействия нужно описать в файле docker-compose.yml. Вот мой:

./docker-compose.yml

nginx:  dockerfile: ./Dockerfile # путь до докер файла указываем относительно директории в build  build: ./contaners/nginx  ports:   - 80:80  volumes:   - ./logs:/etc/logs/nginx  volumes_from:   - fpm:rw  environment:   - NGINX_HOST=localhost   - NGINX_PORT=80  command: nginx -g "daemon off;" # Можно было указать в докер-фале, но можно и здесь)  links:   - fpm fpm:  dockerfile: ./Dockerfile  build: ./contaners/fpm  volumes:   - ./php-code:/var/www:rw

Замечание по поводу указания относительных путей

Если мы указываем относительные пути к файлам и деректориям, то они должны обязательно начинаться с точки (как указание текущей директории), т.е., например, такой путь contaners/nginx/Dockerfile — будет интерпретирован не верно.

Теперь можно запустить наши контейнеры:

docker-compose up -d

аргумент -d

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

Все, наши контейнеры работают и линкуются, но кое-что я сделал не так, а именно — мы для запуска контейнера всегда ссылаемся на Dockerfile, это не очень удобно. Сделаем так:

docker ps CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                                NAMES 2d6263b52380        test_nginx          "nginx -g 'daemon off"   8 minutes ago       Up 8 minutes        443/tcp, 0.0.0.0:8080->80/tcp        test_nginx_1 04370a9e1c73        test_fpm            "php-fpm"                8 minutes ago       Up 8 minutes        9000/tcp                             test_fpm_1  docker tag 2d6263b52380 my-login/repo:nginx docker tag 2d6263b52380 my-login/repo:fpm  docker push my-login/repo:nginx docker push my-login/repo:php7-fpm

Теперь наши контейнеры управляются через docker hub и Dockerfile’ы нам больше не нужны.
Исправим docker-compose.yml:

./docker-compose.yml

nginx:  image: my-login/repo:nginx  ports:   - 80:80  volumes:   - ./logs:/etc/logs/nginx  volumes_from:   - fpm:rw  environment:   - NGINX_HOST=localhost   - NGINX_PORT=80  command: nginx -g "daemon off;" # Можно было указать в докер-фале, но можно и здесь)  links:   - fpm fpm:  image: my-login/repo:php7-fpm  volumes:   - ./php-code:/var/www:rw

А вот теперь я понял, что забыл добавить расширение pcntl для php. Но это легко поправить.
Для начала подключимся к нужному контейнеру:

docker exec -it 04370a9e1c73 bash

И добавить необходимое расширение:

docker-php-ext-install pcntl

Отлично, в контейнер добавили, но мы же хотели использовать docker hub в качестве VCS — значит надо закомитить изменения:

docker commit -m "added pcntl ext" 04370a9e1c73 my-login/repo:php7-fpm

и запушить в репозиторий:

docker push my-login/repo:php7-fpm

Добавим еще контейнеры баз данных (postgresql и mongodb):

./docker-compose.yml

nginx:  image: my-login/repo:nginx  ports:   - 80:80  volumes:   - ./logs:/etc/logs/nginx  volumes_from:   - fpm:rw  environment:   - NGINX_HOST=localhost   - NGINX_PORT=80  command: nginx -g "daemon off;"  links:   - fpm fpm:  image: my-login/repo:php7-fpm  volumes:   - ./php-code:/var/www:rw links:   - mongo   - postgres mongo:  image: mongo  ports:   - 27017:27017 # Проброс портов для внешнего доступа   volumes:  - ./database/mongo:/data/db postgres:  image: postgres:latest  ports:   - 5432:5432 # Проброс портов для внешнего доступа   volumes:   - ./database/postgres:/data/postgres  environment:   POSTGRES_PASSWORD: <myPassword>   POSTGRES_USER: postgres   PGDATA : /data/postgres

И теперь выполняем:

docker-compose up -d

Докер добавит нам новые контейнеры к уже запущенным. Но я открыли порты для внешнего доступа, но мы указали пароль только для PostgreSql, нужно тоже самое сделать и для mongodb — как это сделать (и не только) подробно описано здесь.

Add the Initial Admin Use For MongoDB

docker exec -it some-mongo mongo admin connecting to: admin > db.createUser({ user: 'jsmith', pwd: 'some-initial-password', roles: [ { role: "userAdminAnyDatabase", db: "admin" } ] }); Successfully added user: {     "user" : "jsmith",     "roles" : [         {             "role" : "userAdminAnyDatabase",             "db" : "admin"         }     ] }

Базы данных из php теперь доступны по хостам postgres и mongo соответственно, т.е. для подключения, например, к mongodb мы должны написать следующее:

$manager = new MongoDB\Driver\Manager("mongodb://mongo:27017");

На этом все, спасибо за внимание. Прошу учесть, что все описанное является исключительно моим собственным опытом и не претендует на звание идеального подхода к настройке окружения через docker.
ссылка на оригинал статьи https://habrahabr.ru/post/317504/


Комментарии

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

Ваш адрес email не будет опубликован. Обязательные поля помечены *