I will show you one way to deploy your docker images to your remote server via GitLab CI
In this article
Build deploy pipeline
First we need to create a
.gitlab-ci.yml file at the root of our project. Since we want to build our project into a docker image we will
run the pipeline inside another docker. At the very beginning of our pipeline file we define the image in which we will run the pipeline:
Next we define some global variables which we can reference throughout the pipeline
variables: DOCKER_DRIVER: overlay2 DOCKER_TLS_CERTDIR: "" APP_VERSION: "1.3.0" services: - docker:19.03.5-dind
We will organize our
.gitlab-ci.yml file into different stages:
stages: - image - transfer - deploy
image: at this stage we will build our project into a new docker image
transfer: upload our newly built docker image to Gitlab registry
deploy: pull the docker image from Gitlab registry to our own server and run the image
Lets build our image first:
build_image: stage: image only: - master script: - docker build --no-cache=true --pull -f ./Dockerfile -t $CI_REGISTRY_IMAGE:$APP_VERSION .
What’s happening here?
build_image: This is how I called our first stage. You can name it as you wish
stage: image: This task belongs to the image stage
Next we instruct this stage to run only on our master branch
only: - master
script: section we put our instructions on what this task has to do for us
- docker build --no-cache=true --pull -f ./Dockerfile -t $CI_REGISTRY_IMAGE:$APP_VERSION .
Build our actual docker image and name it
$CI_REGISTRY_IMAGE:$APP_VERSION. $CI_REGISTRY_IMAGE is a built in Gitlab global variable and refers to the name of gitlab repo and
$APP_VERSION is our application version we defined at
the beginning of our config file
transfer_image: stage: transfer script: - docker login -u gitlab-ci-token -p $CI_BUILD_TOKEN $CI_REGISTRY - docker push $CI_REGISTRY_IMAGE:$APP_VERSION only: - master
Before we can push anything to Gitlab registry, Gitlab requires that we authorize ourselves. We achieve this with
Then simply issue
$CI_REGISTRY_IMAGE is another predefined global variable which contains the gitlab registry uri.
The only step left is to deploy and run our image on our server.
In order to ssh from Gitlab pipeline to our server we have to setup ssh keys.
In this stage we are also defining custom variables
$SSH_PRIVATE_KEY. Generally, we try to avoid hardcoding sensitive data such as keys,
passwords… etc. in our application code. Gitlab allows us to configure sensitive data inside their Dashboard.
Login to your Gitlab dashboard, go to your project and navigate to Settings -> CI / CD
Navigate to the Variables section and click on the
Expand button (top-right). Create
$SSH_PRIVATE_KEY variables. As a general
note you should mask variables with sensitive information so they don’t appear in your Gitlab logs. In the
$SSH_PRIVATE_KEY put your private ssh key that you generated previously in base64 encoding.
You can base64 encode your private key by running in your terminal:
$ cat ~/.ssh/your_private_key | base64
$DESTINATION_HOST put the IP of your server.
deploy image: stage: deploy variables: DOCKER_HOST: ssh://user@$DESTINATION_HOST before_script: - 'which ssh-agent || ( apt-get update -y && apt-get install openssh-client -y )' - eval $(ssh-agent -s) - echo "$SSH_PRIVATE_KEY" | base64 -d | tr -d '\r' | ssh-add - > /dev/null - mkdir -p ~/.ssh - chmod 700 ~/.ssh - ssh-keyscan -t rsa $DESTINATION_HOST >> ~/.ssh/known_hosts script: - docker login -u gitlab-ci-token -p $CI_JOB_TOKEN $CI_REGISTRY - docker pull $CI_REGISTRY_IMAGE:$APP_VERSION - docker run --name my_image -d $CI_REGISTRY_IMAGE:$APP_VERSION only: - master
First and very important we define a global variable
DOCKER_HOST. When this variable is defined docker will use it automatically to execute docker over ssh commands. We will take advantage of it to deploy the image.
variables: DOCKER_HOST: ssh://user@$DESTINATION_HOST
- docker login -u gitlab-ci-token -p $CI_JOB_TOKEN $CI_REGISTRY - login to Gitlab from your server to authenticate
- docker pull $CI_REGISTRY_IMAGE:$APP_VERSION - pull the newly created image to your server
- docker run --name my_image -d $CI_REGISTRY_IMAGE:$APP_VERSION - finally we run our image on our server
before_script section we load our private ssh key to the ssh agent so we can access our server
Now go ahead and run a new pipeline in the Gitlab Dashboard by navigation to CI/CD > Pipelines and click on the Run Pipeline button.
As a side note you might want to increase your SSH sessions on your host. By default the ssh config is located in
/etc/ssh/sshd_config. Set the
MaxSessions to something bigger than the default 10. I usually set this to 1000
You just saw how to build, push and deploy a docker image to your server. Such build process allows us to concentrate on developing our application code, commit, push and everything will be deployed to your live server by Gitlab CI.