How To Deploy A Docker Image To A Server Using GitLab CI CD

2 Comments
Published: 16.07.2023

Do you want to learn how to deploy your docker image to your server automatically and, in the same run, update your container? In this guide, we will do exactly that! We will store the image inside GitLab’s Container Registry and then create a Pipeline using GitLab CI CD to deploy it onto the server whenever we push a change!

  1. Store docker image in GitLab’s Container Registry
  2. Running the container on your server
  3. Automate the deployment of your application using GitLab CI CD
  4. Conclusion

You do need a Docker image for this guide. If you do not have an image yet, check out my last post on creating one here.

Server icon

VPS Hosting Course

Learn everything you need to know about servers and hosting your own applications!
Don’t want to read? Watch the video instead!

Store docker image in GitLab’s Container Registry

We will use the GitLab Container Registry to store our Docker image, which allows us to access it from anywhere, especially our server. To store an image in the GLCR, we first need to create a GitLab Personal Access Token (PAT). For more details on the scopes you need and other information, you can check out the GitLab documentation here. If you want to get started quickly, you can use this link, which includes all the required scopes: https://gitlab.com/-/profile/personal_access_tokens?name=container+registry&scopes=write_registry,read_registry

After you click the link, you need to specify the duration and save the PAT value somewhere secure. We will need it in the next steps.

Now, open your terminal and follow these steps from the directory containing the Dockerfile:

  1. Store your PAT inside an environment variable: export CR_PAT=<PAT>
  2. Sign in to the container registry: echo $CR_PAT | docker login registry.gitlab.com -u <username> --password-stdin
  3. Build and upload the container image: export IMAGE=registry.gitlab.com/programonaut/docker-image-gitlab:latest && docker build . -t $IMAGE && docker push $IMAGE

By following these steps, your Docker image will be built and uploaded to the GLCR, and you will be able to access it from your server using the specified image tag. You need to run steps 1 and 2 on your server as well.

Need help or want to share feedback? Join my discord community!

Running the container on your server

The next step is to create a docker-compose.yml file on our server (inside of /home/<username>/<project>), which is a template for our Docker container. This way, we can easily move it to another machine or rebuild the containers. Inside the file, we specify the name of the service, the image, and the ports to use:

services:
  frontend:
    container_name: frontend
    image: registry.gitlab.com/<username>/<project-name>:latest
    ports:
      - 80:80

After creating the docker-compose.yml file, we can build the container by running docker compose up -d. This command will start the container in detached mode, meaning it runs in the background. To check if your container can be built. If everything works correctly, you can access it under http://<server-ip>. To learn how to connect it with a domain, check this post here.

KOFI Logo

If this guide is helpful to you and you like what I do, please support me with a coffee!

Automate the deployment of our application using GitLab CI CD

Automating the deployment of our application significantly reduces manual work and speeds up the deployment process. Before creating the variables and the GitLab Pipeline, we need to set up a new SSH key. To do so, log in to your server as the user you want to run the pipeline as and follow these steps:

  1. Check that user has access to the directory containing the repository and is able to run Docker
  2. Create an SSH key: ssh-keygen -t rsa -b 4096
  3. Copy the content of the key file in base64 encoded (this is needed to store it in the GitLab variables in the next step): cat <path/to/private/key> | base64 -w0
  4. Add the public key to the authorized_keys file: cat <path/to/public/key> >> ~/.ssh/authorized_keys

After creating the SSH key, we need to create the following variables in the repository by going to Settings > Secrets and Variables > Actions:

Once the secrets are set up, we can create the following action inside the file .gitlab-ci.yml. The action first builds the image and pushes it to the registry inside the publish job. It then pulls it onto the server and updates the container in the deploy job.

stages:
  - publish
  - deploy

variables:
  REGISTRY: registry.gitlab.com
  IMAGE_NAME: $GITLAB_USER_LOGIN/$CI_PROJECT_NAME

publish:
  image: docker
  stage: publish
  services: 
    - docker:dind
  before_script: 
    - echo $PAT | docker login $REGISTRY -u $GITLAB_USER_LOGIN --password-stdin
  script:
    - docker build . --tag $REGISTRY/$IMAGE_NAME
    - docker push $REGISTRY/$IMAGE_NAME

deploy:
  image: ubuntu:latest
  stage: deploy
  only: 
    - main
  before_script:
    - apt-get -yq update
    - apt-get -yqq install ssh
    - install -m 600 -D /dev/null ~/.ssh/id_rsa
    - echo "$SSH_PRIVATE_KEY" | base64 -d > ~/.ssh/id_rsa
    - ssh-keyscan -H $SSH_HOST > ~/.ssh/known_hosts
  script:
    - ssh $SSH_USER@$SSH_HOST "cd $WORK_DIR && docker compose pull && docker compose up -d && exit"
  after_script:
    - rm -rf ~/.ssh

This job basically logs into the server, pulls the new version of the image, and then rebuilds the containers.

Conclusion

In this guide, you learned how to create a GitLab CI CD to deploy a docker image to your server automatically! The pipeline first builds the Docker image, pushes it to GitLab’s Container Registry, pulls the new version onto the server, and updates the container!

If you have any questions feel free to comment, join my discord, or email me.

[convertkit form=2303042]

Discussion (2)