Deploy using github actions and packages

Guide to setting up deployment via ssh and docker containers to github. We will deploy to a server running Ubuntu 23.04.


Server preinstallation

We will need docker and git.

Let's configure access to our server

To do this, we will create a new user, under which we will go from github actions:

sudo adduser smith

Let's add sudo access

sudo usermod -aG sudo smith

Let's allow our user to execute docker commands without a password

sudo usermod -aG docker smith

To access from github, we will create an ssh key and add it to the authorized keys:

ssh-keygen
cp .ssh/id_rsa.pub .ssh/authorized_keys

GitHub setup

Let's create a PAT (personal access token) on the page – Personal Access Tokens (Classic) (github.com) . It is important to save it somewhere for a while. If you do it for an organization, then it has a different page.

Add secrets to the turnip (settings -> Secrets -> Actions):

  • PAT – personal token

  • SSH_HOST – host of the machine on which we will deploy the container

  • SSH_PRIVATE_KEY – private key of the user smith

  • SSH_USER – user name, smith

Create a file in turnip docker-compose.yml with our service:

services:
  example_app:
    container_name: example_app
    image: ghcr.io/your_nick/example_app:latest
    volumes:
      - ~/data:/app/data

Setting up github workflow, file .github/workflow/deploy.yml:

name: deploy

on:
  pull_request:
    types:
      - closed
    branches: [ "main" ]

jobs:

    build:
        name: Build
        runs-on: ubuntu-latest

        steps:
        - uses: actions/checkout@v3
        - name: Login
          run: |
            echo ${{ secrets.PAT }} | docker login ghcr.io -u ${{ github.actor }} --password-stdin
        - name: Build and Publish
          run: |
            docker build . --tag ${{ env.DOCKER_TAG }}
            docker push ${{ env.DOCKER_TAG }}

    deploy:
        name: Deploy
        runs-on: ubuntu-latest

        steps:
        - uses: actions/checkout@v4
        - name: install ssh keys
          # check this thread to understand why its needed:
          # <https://stackoverflow.com/a/70447517>
          run: |
            install -m 600 -D /dev/null ~/.ssh/id_rsa
            echo "${{ secrets.SSH_PRIVATE_KEY }}" > ~/.ssh/id_rsa
            ssh-keyscan -H ${{ secrets.SSH_HOST }} > ~/.ssh/known_hosts
        - name: create docker compose config
          run: |
            cat docker-compose.yml | envsubst > docker-compose-secret.yml
        - name: copy docker compose config
          run: scp docker-compose-secret.yml ${{ secrets.SSH_USER }}@${{ secrets.SSH_HOST }}:docker-compose.yml
        - name: connect and pull
          run: ssh ${{ secrets.SSH_USER }}@${{ secrets.SSH_HOST }} "docker-compose pull && docker-compose up -d && exit"
        - name: cleanup config
          if: always()
          run: ssh ${{ secrets.SSH_USER }}@${{ secrets.SSH_HOST }} "rm docker-compose.yml"
        - name: cleanup keys
          if: always()
          run: rm -rf ~/.ssh docker-compose-secret.yml

In this case, the build and deployment will take place during the merge of the pull request.

Docker-compose will download the image from ghcr.io without credentials, so we need to make our package public. On the github profile page, look at the packages tab. Select the package and open access in the Package settings section.

There is an option to work with a private package, then you need to use the PAT file everywhere, the workflow config will be a little more complicated.

PS:

That's all. Write how you deploy your projects using github. Probably my option is not the most convenient.

Similar Posts

Leave a Reply

Your email address will not be published. Required fields are marked *