Развертывание Node.js Docker с нулевым временем простоя

Развертывание Node.js Docker с нулевым временем простоя

У меня есть приложение React/Node.js, работающее на одном сервере с использованием docker-compose. Я пытаюсь добиться развертывания с нулевым временем простоя для моего приложения React. Прямо сейчас процесс выполняет сборку webpack (заменяет файлы в моей папке dist), а затем docker down и docker up. Весь этот процесс занимает около 2-3 минут. Я понял, что с помощью docker-compose я могу масштабировать свой контейнер вверх/вниз, но я не уверен, как только отправить свой код на один из них и пересобрать webpack. Я действительно не хочу использовать Kubernetes/Swarm или Openshift, так как это немного излишне. Мне интересно, добился ли кто-нибудь чего-то похожего.

Мой docker-compose выглядит так:

node:
    build:
        context: ./env/docker/node
        args:
            - PROJECT_ROOT=/var/www/app
    image: react_app:rapp_node
    command: "npm run prod"
    expose:
        - "3333"
    networks:
        - react-net
    volumes_from:
        - volumes_source
    tty: false

nginx:
    env_file:
        - ".env"
    build:
        context: ./env/docker/nginx
    volumes_from:
        - volumes_source
    volumes:
        - ./env/data/logs/nginx/:/var/log/nginx
        - ./env/docker/nginx/sites/node.template:/etc/nginx/node.template
    networks:
        - react-net
        - nginx-proxy
    environment:
        NGINX_HOST: ${NGINX_HOST}
        VIRTUAL_HOST: ${NGINX_VIRTUAL_HOST}
        LETSENCRYPT_HOST: ${NGINX_VIRTUAL_HOST}
        ESC: $$
    links:
        - node:node
    command: /bin/sh -c "envsubst < /etc/nginx/node.template > /etc/nginx/sites-available/node.conf && nginx -g 'daemon off;'"

volumes_source:
    image: tianon/true
    volumes:
        - ./app:/var/www/app

А мой nginx выглядит примерно так:

server {
server_name www.${NGINX_HOST};
return 301 ${ESC}scheme://${NGINX_HOST}${ESC}request_uri;
}

server {
listen 80;
server_name ${NGINX_HOST};

root /var/www/app;

location / {
proxy_pass http://node:3333;
proxy_http_version 1.1;
proxy_set_header Upgrade ${ESC}http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host ${ESC}host;
proxy_cache_bypass ${ESC}http_upgrade;
}
}

решение1

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

Но, если вы хотите именно то, что написали (но это не верный путьсовсем), вы можете, например, запустить скрипт в контейнере, который извлечет новую версию вашего приложения, соберет ее и переключит символическую ссылку со старой версии на новую, что можно сделать атомарно, например, так: ln -s new current_tmp && mv -Tf current_tmp current.

Итак, структура каталогов будет такой: /var/www/app - symlink to your current version /var/www/app_v1 - directory with current version, which symlinked to "/var/www/app" /var/www/app_v2 - directory with new version

Теперь вы можете выполнить команду ln -s /var/www/app_v2 /var/www/app_v2_sym && mv -Tf /var/www/app_v2_sym /var/www/appдля переключения текущей версии приложения, используемого Nginx.

решение2

Я настоятельно рекомендую для этого простой одноузловой swarm. Это идеальное решение для случаев, когда вам нужно нулевое время простоя во время обновлений, но вы не можете или не нуждаетесь в многоузловой высокой доступности. Он действительно не добавляет накладных расходов или дополнительных административных обременений и использует те же файлы компоновки.

Да, вам действительно следует создавать новую версию образа с вашим кодом при каждом коммите, который вы планируете отправить на этот сервер. Инструменты ожидают этот тип рабочего процесса, поэтому вам будет легче, если вы примете этот рабочий процесс. Docker Hub поддерживает выполнение этого для вас при каждом коммите в ветку (бесплатно, если исходный код открыт, и все равно бесплатно для одного частного репозитория) GitHub и BitBucket. Вот как это будет работать в одноузловом рое, предполагая, что вы создаете новые образы каждый раз в Docker Hub:

  1. Предполагая, что у вас установлена ​​последняя стабильная версия Docker (17.12 на момент написания этой статьи)
  2. docker swarm initи теперь у вас есть одноузловой рой. Вот и все. (Если у меня может быть только один сервер для развертывания докеров наЯ всегда использую single-node-swarm, а не docker-compose по ряду веских причин.
  3. С небольшими изменениями ваш файл Compose можно использовать как файл стека дляdocker stack deploy -c compose-file.yml stackname
  4. Чтобы обеспечить развертывание без простоев, вам необходимо:добавить проверки здоровьяв ваши контейнеры node/nginx, чтобы они знали, когда приложение действительно «готово к соединениям». Swarm также использует это во время обновлений сервисов, поэтому это ключ.
  5. Если вы хотите, чтобы Swarm сначала добавил новый контейнер, перед удалением старого контейнера добавьте order: start-firstвhttps://docs.docker.com/compose/compose-file/#update_config.
  6. Затем просто измените теги изображений в файле Compose, возможно, myuser/myrepo:1.0на myuser/myrepo:2.0, а затем снова запустите ту же команду развертывания стека, и Swarm обнаружит различия и обновит службу новым образом (заменив контейнер).

Чтобы проверить это, используйте httping, чтобы убедиться, что он по-прежнему доступен удаленно во время процесса обновления.

Связанный контент