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.