4 заметки с тегом

docker-compose

Как подружить docker, localhost и HTTPS

Когда разрабатываешь веб-сервис, который крутится на проде по HTTPS, есть большой соблазн не запариваться и работать локально по HTTP. Потому что так проще, да и в целом же всё работает плюс-минус одинаково. Если сервис простой, то скорее всего никаких проблем не всплывёт, но если сервис не монолитный и зависит от внешних сервисов или сам предоставляет АПИ клиентам, то проблемы с CORS неизбежны. И обычно эти проблемы обнаруживаются слишком поздно — либо на стейджинге, либо даже после релиза на продакшен.

Браузер начинает ругаться, что запросы с HTTPS на HTTP или наоборот не безопасны, сторонние сервисы перестают отвечать, так как по HTTP работали только тестовые стенды, с которыми вы и работали.

Решение простое — нужно не лениться и максимально приблизить локальную среду к боевой. Благо это задача из серии один раз сделал и используешь для всех последующих проектов.

Docker на продакшене

Если у вас продакшен без Docker, то вам поможет статья — Как получить бесплатный SSL-сертификат и установить его на Nginx.

В этой статье я рассматриваю только локальную сборку через docker-compose, потому что на продакшене, как ни странно, это немного проще. Достаточно выполнить понятную инструкцию по настройке Certbot и/или добавить соответствующий докер-образ с Docker Hub.

Docker на localhost

См. как запустить сайт через docker-compose на примере докеризации Эгеи.

На локалхосте Certbot не подойдёт, так как ему нужно реально существующее доменное имя и доступный через интернет сайт. Поэтому прописать локальный адрес в /etc/hosts не поможет. Решение — выпустить свой самоподписанный сертификат. Да, он не будет приниматься никем, кроме нашей системы, но для локальной разработки этого и не нужно.

Создаём доменное имя

Во-первых, создадим локально доменное имя, чтобы оно было похожим на боевое, а не обычный и скучный localhost. Например, docker.loc для основного сайта и api.docker.loc для API:

$ sudo vim /etc/hosts
127.0.0.1       localhost
127.0.0.1       docker.loc
127.0.0.1       api.docker.loc
...

Если для вашего сервиса необходимо несколько доменов, то пропишите их ниже по аналогии.

Выпускаем свой SSL-сертификат

Для реальных сайтов SSL-сертификаты выдаются специальными сертификационными центрами за деньги. За это они потом могут подтвердить верность домена по запросу любого браузера. Мы же выпустим свой сертификат и сами его подтвердим.

SSL-сертификат создаётся одной командой и состоит из двух частей: публичного сертификата и секретного ключа.

openssl req -x509 -out docker.loc.crt -keyout docker.loc.key \
  -newkey rsa:2048 -nodes -sha256 \
  -subj '/CN=docker.loc' -extensions EXT -config <( \
   printf "[dn]\nCN=docker.loc\n[req]\ndistinguished_name = dn\n[EXT]\nsubjectAltName=DNS:docker.loc\nkeyUsage=digitalSignature\nextendedKeyUsage=serverAuth")

Файлы docker.loc.crt и docker.loc.key будут сохранены в той папке, откуда вы запускаете команду.

Добавляем сертификаты в ОС

Ниже пример, как это сделать на Mac OS X.

  1. Найдите сертификат docker.loc.crt в Finder (или можно в нужной папке консоли ввести «open .»)
  2. Дважды кликните по нему, появится окно.
  1. Введите пароль администратора
  2. Теперь нужно найти этот сертификат в Keychain Access и выбрать Trust Always

Добавляем сертификаты в docker-compose сборку

Сертификаты нужно положить в контейнер с веб-сервером. Я приведу пример для Nginx и сборки по типу https://github.com/pluseg/e2-docker.

Расположение сертификатов и конфигов

В этой сборке папки из app/docker/nginx монтируются прямо в nginx-контейнер. Поэтому удобно расположить файлы так:

<project root>
- app
--- docker
----- nginx
------- conf.d
--------- docker.loc.conf
------- ssl
--------- docker.loc.crt
--------- docker.loc.key

Пример docker.loc.conf (проект на PHP + Symfony)

# лучше с php соединять через socket
upstream php-upstream { server web:9000; }

# Редиректим HTTP на HTTPS
server {
       listen         80;
       listen    [::]:80;
       server_name    docker.loc;
       return         301 https://$server_name$request_uri;
}

server {
    listen 443 ssl;
    listen [::]:443 ssl;

    root /var/www/html/docs;

    server_name            docker.loc;
    ssl_certificate          /etc/nginx/ssl/docker.loc.crt;
    ssl_certificate_key   /etc/nginx/ssl/docker.loc.key;
    ssl_protocols           TLSv1 TLSv1.1 TLSv1.2;
    ssl_ciphers         EECDH+CHACHA20:EECDH+AES128:RSA+AES128:EECDH+AES256:RSA+AES256:EECDH+3DES:RSA+3DES:!MD5;

    location / {
    	try_files $uri /index.php$is_args$args;
    }

    location ~ ^/(index|app|app_dev|config)\.php(/|$) {
        fastcgi_pass php-upstream;
        fastcgi_split_path_info ^(.+\.php)(/.*)$;
        include fastcgi_params;
        fastcgi_param  SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
        fastcgi_param DOCUMENT_ROOT $realpath_root;
        fastcgi_read_timeout 300;
    }

    error_log /var/log/nginx/docker.loc-error.log;
    access_log /var/log/nginx/docker.loc-access.log;
}

Пример docker-compose.yml

Добавляем 443 порт и несколько volume с конфигами и сертификатами.

version: '3.2'
services:
    ...
    nginx:
        image: nginx:latest
        ports:
            - 80:80
            - 443:443
        volumes:
            - ./app/docker/nginx/conf.d:/etc/nginx/conf.d
            - ./app/docker/nginx/ssl:/etc/nginx/ssl
            - ./:/var/www/html
            - ./var/logs/nginx:/var/log/nginx
        command: /bin/bash -c "exec nginx -g 'daemon off;'"

Запускаем и проверяем

docker-compose up -d --build

Принципы работы docker и примеры использования docker-compose

Артём Матяшов записал отличный полуторачасовой урок про основы докера. Можно посмотреть на x1.5 за час.

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

Однозначно лайк!

Как ускорить docker-compose на Mac OS X — docker-sync

Хорошая статья про настройку docker-sync — короче и ёмче, чем в официальной документации:
https://dev.to/kovah/cut-your-docker-for-mac-response-times-in-half-with-docker-sync-1e8j

1. Установка через терминал


gem install --user-install docker-sync
# or globally via
sudo gem install docker-sync

2. Добавить файл docker-sync.yml в корень проекта (пример для Symfony)


version: "2"

options:
    compose-dev-file-path: 'docker-compose-sync.yml' # Если хочется изменить дефолтный файл docker-compose-dev.yml
syncs:
    PROJECT-data-sync:  # Это надо заменить на любое уникальное имя
        src: './'
        host_disk_mount_mode: 'cached'
        sync_excludes:
            - '.git'
            - '.idea'
            - 'app/cache/*'
            - 'app/logs/*'

3. Добавить файл docker-compose-sync.yml (или *-dev.yml по умолчанию) в корень проекта:


version: '3.2'

services:
    web:
        volumes:
            - ./composer.json:/var/www/html/composer.json
            - ./composer.lock:/var/www/html/composer.lock
            - PROJECT-data-sync:/var/www/html:nocopy

volumes:
    PROJECT-data-sync:
        external: true

4. Запускаем в терминале в корне проекта


docker-sync start
# нужно подождать, пока всё синхронизируется
docker-compose -f docker-compose.yml -f docker-compose-sync.yml up -d

Запуск через docker-sync-stack start делает две команды выше, но остаётся висеть в консоли, а не уходит в фоновые процессы.

Чтобы остановить, делаем ровно обратное


docker-compose stop
docker-sync stop