Менял недавно виртуальный сервер, и пришлось настраивать все заново. Я предпочитаю, чтобы сайт был доступен по https и сертификаты letsencrypt получались и продлевались автоматически. Этого можно добиться, если использовать два образа docker nginx-proxy и nginx-proxy-companion.


Это руководство как настроить сайт на docker, с прокси, которое автоматически получает SSL сертификаты. Используется виртуальный сервер CentOS 7.


Я предполагаю, что сервер уже куплен, настроен, вход на него осуществляется по ключу, установлен fail2ban и т.д.


Для начала нужно установить docker.


  1. Сначала нужно установить зависимости

    $ sudo yum install -y yum-utils  device-mapper-persistent-data lvm2
  2. Подключить репозиторий

    $ sudo yum-config-manager  --add-repo  https://download.docker.com/linux/centos/docker-ce.repo
  3. Потом установить докер community edition

    $ sudo yum install docker-ce docker-ce-cli containerd.io
  4. Добавить docker в автозагрузку и запустить

    $ sudo systemctl enable docker
    $ sudo systemctl start docker
  5. Добавить пользователя в группу docker, для того, чтобы получить возможность запускать docker без sudo

    $ usermod -aG docker user

Следующий шаг — установить docker-compose. Утилиту можно установить несколькими путями, но я предпочитаю устанавливать через pip менеджер и virtualenv, чтобы не засорять систему лишними пакетами.


  1. Установить pip

    $ sudo yum install python-pip
  2. Установить virtualenv

    $ pip install virtualenv
  3. Дальше нужно создать папку с проектом и инициализировать ее. Папка со всем нужным для управления пакетами будет называться ve.

    $ mkdir docker
    $ cd docker
    $ virtualenv ve
  4. Чтобы начать пользоваться виртуальным окружением нужно выполнить следующую команду в папке с проектом.

    $ source ve/bin/activate
  5. Можно устанавливать docker-compose.

    pip install docker-compose

    Для того, чтобы контейнеры видели друг друга, создадим сеть. По умолчанию используется драйвер bridge.

    $ docker network create network

    Дальше нужно настроить docker-compose, proxy будет лежать в папке proxy, тестовый сайт в папке test. Для примера я использую доменное имя example.com

    $ mkdir proxy
    $ mkdir test
    $ touch proxy/docker-compose.yml
    $ touch test/docker-compose.yml

    Содержимое proxy/docker-compose.yml



    version: '3'
    
    networks:
      default:
        external:
          name: network
    
    services:
      nginx-proxy:
        container_name: nginx-proxy
        image: jwilder/nginx-proxy
        ports:
          - 80:80
          - 443:443
        volumes:
          - certs:/etc/nginx/certs
          - vhost.d:/etc/nginx/vhost.d
          - html:/usr/share/nginx/html
          - /var/run/docker.sock:/tmp/docker.sock:ro
    
      nginx-proxy-letsencrypt:
        container_name: nginx-proxy-letsencrypt
        image: jrcs/letsencrypt-nginx-proxy-companion
        volumes: 
          - certs:/etc/nginx/certs
          - vhost.d:/etc/nginx/vhost.d
          - html:/usr/share/nginx/html
          - /var/run/docker.sock:/var/run/docker.sock:ro
        environment:
          - NGINX_PROXY_CONTAINER=nginx-proxy
    
    volumes:
      certs:
      vhost.d:
      html:

    Переменная окружения NGINX_PROXY_CONTAINER нужна, чтобы letsencrypt контейнер увидел proxy контейнер. Папки /etc/nginx/certs /etc/nginx/vhost.d и /usr/share/nginx/html должны совместно использоваться и тем и другим контейнером. Для корректной работы letsencrypt контейнера приложение должно быть доступно и по 80 и по 443 порту.


    Содержимое test/docker-compose.yml


    version: '3'
    
    networks:
      default:
        external:
          name: network
    
    services:
    
      nginx:
        container_name: nginx
        image: nginx:latest
        environment:
          - VIRTUAL_HOST=example.com
          - LETSENCRYPT_HOST=example.com
          - LETSENCRYPT_EMAIL=admin@example.com

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


    Осталось только запустить docker-compose


    $ cd proxy
    $ docker-compose up -d
    $ cd ../test
    $ docker-compose up -d

Комментарии (16)


  1. aol-nnov
    26.03.2019 20:23
    -1

    Или просто начать использовать, например, traefik вместо этой этажерки. (Да, сам начинал с jwilder, но было это почти два года назад) :)


    1. also_east Автор
      26.03.2019 20:49

      Спасибо, почитал про traefik. Когда представится возможность, попробую и с ним поэкспериментировать.


    1. stilet69
      26.03.2019 21:28
      +1

      В чем преимущество traefik перед nginx?


      1. aol-nnov
        26.03.2019 22:16

        Кто сказал nginx? Может, статью, всё-таки, осилить, а потом перечитать мой комментарий в свете полученной из статьи информации?

        Поясняю: traefik (один за всё, описанное в статье отвечает. однако имеет намного более широкие возможности по кофигурированию) тут противопоставляется подобию ingress controller-а из желудей и пластилина — тому, что в статье (в среднем, три контейнера: генератор конфигов, acme client и уже потом nginx)


  1. Gwynn
    26.03.2019 21:24

    Уже несколько лет использую acme.sh. Просто, удобно и не надо тянуть еще под дистрибутива левых зависимостей с офф.клиентом. Умеет делать подтверждения через AcmeDNS (поддерживает кучу ДНС провайдеров), автопродление (через крон) и т.п.


    1. kmansoft
      26.03.2019 22:01

      И ещё acme.sh поддерживает ECDSA сертификаты уже сейчас в отличие от certbot (там обещают в середине этого года).


      Наверное реальной надобности в этом сейчас нет, но мне понравилось, прикольно.


  1. porn
    26.03.2019 22:26

    Ещё можно использовать что-то из этого: hub.docker.com/u/certbot
    У меня, например, получение сертификатов свелось к такой команде:

    Показать
    docker run -it --rm --name certbot   -v "/etc/letsencrypt:/etc/letsencrypt"   -v "/var/lib/letsencrypt:/var/lib/letsencrypt"   -v "/var/log/letsencrypt:/var/log/letsencrypt"   -v "/etc/certbot/.secrets:/.secrets:ro"   certbot/dns-digitalocean certonly     --agree-tos     --register-unsafely-without-email     --manual-public-ip-logging-ok     --preferred-challenges dns-01     --server https://acme-v02.api.letsencrypt.org/directory     --dns-digitalocean     --dns-digitalocean-credentials /.secrets/digitalocean.ini     --dns-digitalocean-propagation-seconds 30     -d "example.com"     -d "*.example.com"


    1. kmansoft
      27.03.2019 07:03

      Напомнило "всего три команды, чтобы поставить Gentoo"


      https://bash.im/quote/394695


  1. aol-nnov
    26.03.2019 22:43

    да, кстати, «забавный факт»

    > /var/run/docker.sock:/var/run/docker.sock:ro

    это лишь защищает файл /var/run/docker.sock от удаления в контейнере, но никак не запрещает запись в этот файл. пруф, например

    можно что-то типа tecnativa/docker-socket-proxy приделать и рулить доступом через него, как тут.


  1. keydon2
    27.03.2019 09:28

    А зачем тут вообще докер?


    1. also_east Автор
      27.03.2019 19:04

      У меня на работе несколько программистов работает. Под каждый их проект делать отдельную виртуальную машину расточительство. Там может быть проект с nodejs, а рядом php скрипты. Эта штука хорошо работает, просто при создании контейнера под проект пару переменных указал — и все, клиент может посмотреть что в итоге получилось.


  1. Jokerzp
    27.03.2019 11:29

    А в чем преимущества такого подхода, если сравнивать с классическим Certbot?


    1. also_east Автор
      27.03.2019 11:44

      Преимуществ несколько.

      nginx-proxy контейнер перенаправляет трафик в зависимости от того, к какому хосту обратился клиент. Т.е. по порту, допустим, 443, будет доступно несколько контейнеров.

      nginx-proxy-companion автоматически получает или продлевает сертификат.

      Вся настройка, в итоге, сводится к добавлению переменных VIRTUAL_HOST, LETSENCRYPT_HOST и LETSENCRYPT_EMAIL в docker контейнер.


  1. also_east Автор
    27.03.2019 11:42

    del


  1. kovalr
    27.03.2019 19:11

    Nginx with automatic let's encrypt (docker image)
    github.com/umputun/nginx-le


    1. also_east Автор
      27.03.2019 19:13

      Возможно, просто когда я столкнулся с проблемой, нагуглил именно это решение.