Рубрики
Uncategorized

Разверните ваши контейнеры Docker с нулевым временем

Разверните ваше приложение с нулевым временем, используя Docker-Compose, просто и бесплатно. Помечено с докером, облаком, дежоптом.

Мне нравится использовать Docker, везде, а также, особенно докер-составляющую и его магию.

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

В этой статье я объясню, как вы можете развернуть ваше приложение с нулевым временем, используя только ваш файл Compose Docker.

Установка Docker-Compose

Это файл Docker-Compose, который я объясню, что будет добавлено, что будет добавлено, чтобы сделать работу нулевого простоя.

Приложение/Docker-Compose.yml

version: "3.6"

services:
  app_db:
    image: postgres
    restart: always
    ports:
      - 5432:5432
    container_name: pqdb
    networks:
      - db_nw

  app_server:
    build:
      dockerfile: Dockerfile.server
    ports: 
      - "8989"
    networks: 
      - db_nw
      - web_nw
    restart: always
    volumes:
      - ../:/apps/go-app
    depends_on:
      - app_db  

  app_nginx:
    image: nginx:latest
    container_name: nginx
    restart: always
    volumes:
      - ./cfg/nginx.conf:/etc/nginx/nginx.conf
    ports:
      - 8888:80
    networks:
      - web_nw
    depends_on: 
      - app_server

networks:
  db_nw:
    driver: bridge
  web_nw:
    driver: bridge

У меня есть 3 службы, app_db, app_server и app_nginx. Здесь ничего не хочет. Самое важное Piece Здесь не устанавливает имя контейнера, ни отображения порта («1234: 0987») в службе App_server, я скажу вам, почему позже.

Но вы, возможно, задаетесь вопросом — это пользовательские сети, необходимые для создания этой работы? короткий ответ

Позвольте мне объяснить докерные сети первым, потому что она имеет большую роль в создании этих работ.

Docker Networks

Когда вы запустите файл Docker-Compose, Docker подключает ваши услуги к той же сети, которая является сетью по умолчанию называется Bridge, и я думаю, что имя самоуверенно, оно создает мост между услугами, чтобы они могли общаться друг с другом, И забавная часть — это вам не нужно знать каждый IP-адрес контейнера, просто используйте имя сервиса, а Docker будет обрабатывать остальные.

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

Если вы хотите узнать больше о Docker Networks, и вы должны делать, читать Эта статья

Nginx.

Nginx также является важным обслуживанием здесь, я покажу вам файл конфигурации, а затем объясните.

Приложение/cfg/nginx.conf

http {
   server {
      listen 80;
      location / {
         proxy_pass "http://app_server:8989";
      }      
   }
}

events {}

Это самая базовая конфигурация NGINX на Земле, мы создаем веб-сервер, который слушает в порту 80 и пропускать запросы на наш сервер приложений. Как вы можете видеть, я использую имя сервиса здесь, Docker переведет это на соответствующий IP-адрес контейнера.

Теперь, если вы запустите файл Pocker Compose, вы должны быть в состоянии сделать запросы на веб-сервер, который мы сопоставляем его в порт 8888 попробуйте Curl http://localhost: 8888

Но ждать…

Да, вы хотите знать, почему я не поместил имя контейнера и не отображает порт в службу App_server. Правильно ? Ну, просто не настраивая их, позволит Docker принять решение, он создаст имя, которое идентично именному имени сервиса, но суффиксировано с номером/индексом контейнера. Пример, если вы запустите свой Docker Compose файл и введите докер PS. Вы увидите, что имя контейнера App_Server на самом деле App_server_1. ОК, как насчет порта? Также не отображение порта к сервису позволит Docker выбрать динамический порт и сопоставьте его в порт, который мы устанавливаем на службу, каждый раз, когда вы запускаете Docker Compose File, порт изменится.

Веселая часть

Теперь мы сделаем развертывание нулевого простоя. Мы напишем простой и небольшой скрипт Bash, который сделает следующее:

1) Создайте новый экземпляр App_server (С новым изменениям кода) 2) Проверьте, если он работает и работает 3) Перезагрузить nginx (Так что он может распознать новый экземпляр) 4) Удалить старый экземпляр (со старым кодом)

Позвольте мне показать вам сценарий, а потом я объясню, как и почему?

service_name=app_server
nginx_container_name=nginx

reload_nginx() {  
  docker exec $nginx_container_name /usr/sbin/nginx -s reload  
}

# server health check
server_status() {
  # $1 = first func arg
  local port=$1
  local status=$(curl -is --connect-timeout 5 --show-error http://localhost:$port | head -n 1 | cut -d " " -f2)

  # if status is not a status code (123), means we got an error not an http header
  # this could be a timeout message, connection refused error msg, and so on...
  if [[ $(echo ${#status}) != 3 ]]; then
    echo "503"
  fi

  echo $status
}

update_server() {

  old_container_id=$(docker ps -f name=$service_name -q | tail -n1)

  # create a new instance of the server
  docker-compose up --build -d --no-deps --scale $service_name=2 --no-recreate $service_name
  new_container_id=$(docker ps -f name=$service_name -q | head -n1)

  if [[ -z $new_container_id ]]; then
    echo "ID NOT FOUND, QUIT !"
    exit
  fi
  new_container_port=$(docker port $new_container_id | cut -d " " -f3 | cut -d ":" -f2)

  if [[ -z $new_container_port ]]; then
    echo "PORT NOT FOUND, QUIT !"
    exit
  fi

  # sleep until server is up
  while [[ $(server_status $new_container_port) > "404" ]]; do
    echo "New instance is getting ready..."
    sleep 3
  done

  # ---- server is up ---

  # reload nginx, so it can recognize the new instance
  reload_nginx

  # remove old instance 
  docker rm $old_container_id -f

  # reload ngnix, so it stops routing requests to the old instance
  reload_nginx

  echo "DONE !"
}

# call func
update_server

У нас есть 3 функции: 1) Перезагрузка Nginx На самом деле перезагрузка Nginx не вызывает простоя

3) Проверка здоровья сервера

curl -is --connect-timeout 5 --show-error http://localhost:$port

Это вернет заголовки ответа, так как мы можем видеть, что первая строка — это код состояния HTTP

HTTP/1.1 200 OK
Age: ...
Cache-Control: ...
Content-Type: ...
...

Мы хотим первую строку

head -n1

Разделите текст на основе пробелов и получите второе поле, которое 200 в нашем примере

cut -d " " -f2

3) Обновить сервер В этой функции мы получаем текущий или старый идентификатор контейнера сервера, то мы создаем новый экземпляр службы App_server, не касаясь других связанных служб,

docker-compose up -d --no-deps --scale $service_name=2 --no-recreate $service_name

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

Окончательно

Так как это будет работать? Как я буду развернуть мой сервер и обновить его? Если вы запустите скрипт на своей машине, он должен работать на вашем сервере, причина, это как работает Docker, верно?

Вы можете использовать SCP (Безопасная копия) Чтобы скопировать код с локальной машины на сервер, и вы можете использовать одну и ту же команду для обновления кода на сервере

scp USER@IP:~/apps ./local/app

Вы должны использовать Docker-Poompout прежде всего, если ваш первый раз ваш развертывающий код. А затем запустите скрипт update_server, чтобы обновить изменения без простоя.

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

Читать дальше Как вы можете использовать Git для развертывания вашего кода, так как прост в виде Git Push.

Ресурсы

Bash Cheat лист Docker Cheat лист

Оригинал: «https://dev.to/wassimbj/deploy-your-docker-containers-with-zero-downtime-o3f»