Skip to content
Mikhail Prozorov edited this page Nov 4, 2021 · 10 revisions

Текущая версия

Чем хорошо на этот раз:

Работаем через ssh на сервере - быстрый перезапуск контейнера с джанго, другие контейнеры вообще не трогаем.

Разбор workflow

name: ci

###########
# Запускается только при закрытом пул-реквесте в дев
on:
  pull_request:
    types: [ closed ]
    branches: [ dev ]

jobs:
  deploy:

###########
# Проверяем, что пр не просто закрыт, а смерджен
    if: github.event.pull_request.merged == true
    runs-on: ubuntu-latest
    steps:

###########
# этот экшн передает содержимое репозитория в виртуалку
      - name: Checkout
        uses: actions/checkout@v2

###########
# устанавливаем докер в виртуалку
      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v1

###########
# логинимся в ghcr.io
      - name: Login to DockerHub
        uses: docker/login-action@v1
        with:
          registry: ghcr.io
          username: ${{ github.actor }}
          password: ${{ github.token }}

###########
# собираем и отправляем докер образ
      - name: Build and push
        uses: docker/build-push-action@v2
        with:
          push: true
          tags: ghcr.io/${{ github.repository }}:dev

###########
# готовим к отправке docker-compose.yml и docker-compose.env - упаковываем в архив
      - name: Tar
        run: |
          cd ${{ github.workspace }}/deploy-dev
          tar -cf deploy-dev.tar *

###########
# отправляем на наш сервер архив
      - name: upload docker-compose
        uses: appleboy/scp-action@master
        with:
          host: ${{ secrets.SSH_SERVER }}
          username: ${{ secrets.SSH_USER }}
          key: ${{ secrets.SSH_KEY }}
          source: "${{ github.workspace }}/deploy-dev/deploy-dev.tar"
          target: "/srv/netomerch/backend/"

###########
# подключаемся к серверу по ssh и выполняем скрипт
      - name: Connect via SSH, pull, restart
        uses: appleboy/ssh-action@master
        with:
          host: ${{ secrets.SSH_SERVER }}
          username: ${{ secrets.SSH_USER }}
          key: ${{ secrets.SSH_KEY }}
          script: |
###########
# генерируем рандомный SECRET_KEY и кладем его в переменную окружения
            export SECRET_KEY=$(echo $RANDOM | md5sum | head -c 20; echo;)
###########
# название репозитория кладем в переменную окружения - будет использовано в docker-compose
            export REPO_NAME=${{ github.repository }}

            cd /srv/netomerch/backend/

###########
# создаем папку и распаковываем туда файлы, которые передали ранее
            mkdir -p deploy-dev
            chmod 777 deploy-dev
            tar -xvf /srv/netomerch/backend/github/workspace/deploy-dev/deploy-dev.tar -C deploy-dev
            cd deploy-dev && chmod 666 *

###########
# тащим свежий образ из реестра
            docker pull ghcr.io/${{ github.repository }}:dev

###########
# останавливаем контейнер с джанго
            docker-compose stop api

###########
# удаляем контейнер с джанго
            docker-compose rm -f api

###########
# поднимаем джанго, при этом создаётся новый контейнер на основе свежего образа
            docker-compose up -d api

###########
# чистим мусор
            rm -rf /srv/netomerch/backend/github
            for image in $(docker image ls| grep none|awk '{print $3}' | cat) ; do docker image rm "$image"; done

Предыдущая версия

Сделано на основе:

  1. https://matakov.com/udalennyj-deploj-s-pomoshhyu-docker-compose-na-github-actions/

  2. https://github.com/artrey/web-chat/blob/master/.github/workflows/ci.yml

Чем хорош этот workflow?

Для его работы нам достаточно только доступа на удаленную машину с правом запускать docker-compose. Не надо создавать никаких файлов или папок на ней, можно даже вообще к ней не подключаться.

При смене сервера достаточно поменять SSH_SERVER, SSH_USER, SSH_KEY в секретах, и все будет разворачиваться на новом.

Разбираем workflow

name: dev_deploy

###########
# Запускается только при закрытом пул-реквесте в дев
on:
  pull_request:
    types: [ closed ]
    branches: [ dev ]

jobs:
  deploy:
###########
# Проверяем, что пр не просто закрыт, а смерджен
    if: github.event.pull_request.merged == true
    runs-on: ubuntu-latest

###########
# этот экшн передает содержимое репозитория в виртуалку
    steps:
      - name: Checkout
        uses: actions/checkout@v2

###########
# устанавливаем докер в виртуалку
      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v1

###########
# логинимся в ghcr.io
      - name: Login to DockerHub
        uses: docker/login-action@v1
        with:
          registry: ghcr.io
          username: ${{ github.actor }}
          password: ${{ github.token }}

###########
# собираем и отправляем докер образ
      - name: Build and push
        uses: docker/build-push-action@v2
        with:
          push: true
          tags: ghcr.io/${{ github.repository }}:dev

###########
# этот экшн для добавления нашего сервера в known-hosts - это необходимо 
# для дальнейшего подключения к нему с помощью докера
      - name: Setup SSH
        uses: kielabokkie/ssh-key-and-known-hosts-action@v1
        with:
          ssh-private-key: ${{ secrets.SSH_KEY }}
          ssh-host: ${{ secrets.SSH_SERVER }}

###########
# устанавливаем питон в виртуалку
      - name: Setup python
        uses: actions/setup-python@v2

###########
# переходим в папку с проектом
      - name: Pull and restart
        run: |
          cd ${{ github.workspace }}/deploy-dev

###########
# устанавливаем docker-compose в виртуалке
          sudo pip install docker-compose

###########
# генерируем SECRET_KEY для джанго и кладем его в переменные среды
          export SECRET_KEY=$(echo $RANDOM | md5sum | head -c 20; echo;)

###########
# кладем название репозитория в переменные среды для docker-compose
          export REPO_NAME=${{ github.repository }}
           

###########
# Магия! Создаем контекст для докера, в котором подключаемся к удаленному серверу (нашему VPS)
          docker context create remote --docker "host=ssh://${{ secrets.SSH_USER }}@${{ secrets.SSH_SERVER}}"

###########
# говорим докеру, что следующие команды надо выполнять на удаленном сервере
          docker context use remote

###########
# тащим свежий образ
          docker pull ghcr.io/${{ github.repository }}:dev

###########
# останавливаем docker-compose на удаленном сервере
          docker-compose --context remote down

###########
# там же запускаем
          docker-compose --context remote up -d

###########
# эта команда удалит старые образы с версией вида <none>
          for image in $(docker image ls| grep none|awk '{print $3}' | cat) ; do docker image rm "$image"; done

Файлы в deploy-dev

docker-compose.yml

version: '3.7'

services:
  db-postgres:
    image: postgres:11.0-alpine
    env_file:
      - docker-compose.env
    volumes:
      - pg-data:/var/lib/postgresql/data
    networks:
      - backend
    hostname: db-postgres

  api:
    image: ghcr.io/${REPO_NAME}:dev
    env_file:
      - docker-compose.env
    command: sh /netomerch-backend/run.sh
    depends_on:
      - db-postgres
    ports:
      - 8000:8000
    networks:
      - backend
    hostname: api

networks:
  backend:
    name: backend

volumes:
  pg-data:

docker-compose.env

POSTGRES_USER=postgres
POSTGRES_PASSWORD=postgres
POSTGRES_DB=netomerch
DB_ENGINE=django.db.backends.postgresql_psycopg2
DB_NAME=${POSTGRES_DB}
DB_USER=${POSTGRES_USER}
DB_PASSWORD=${POSTGRES_PASSWORD}
DB_HOST=db-postgres
DB_PORT=5432
SECRET_KEY=${SECRET_KEY}
DEBUG=1

Clone this wiki locally