07/01/2020 docker deploy gitlab ci-cd
Recently we discussed a binary file deployment via SSH.
Now we are discussing Docker container deployment with Gitlab CI.
There are some of them against binary file deployment:
docker
utility. When using binary file deployment
we need an additional software like systemd
or supervisor
.
docker
utility.)
All necessary additional programs could be installed inside our docker container during docker image build.
Recently we discussed minimal docker image building for GO program. Let's continue to use that approach.
We are going to use only standard docker
utility options.
We intentionally ignore any external orchestration tools like kubernetes
or nomad
;
We won't use any cloud docker provider, for example, Google Cloud
— all of it
we'll discuss in future articles.
We choose docker swarm
, it is a part of standard docker
utility.
Swarm allows us to manage containers on a remote server that is previously
configured with docker swarm init
or
docker swarm join
commands.
These commands change docker service mode to swarm.
SSH access to the target server is not required, which is an advantage.
docker stack deploy
updates containers using file in docker-compose
format,
so we even don't need to install docker-compose
.
When using docker stack deploy
, which is accessible when docker service
runs in swarm mode, we can pass the exact order in which we want
our containers to be updated and many other deployment options.
By this we can provides smooth update without downtime.
Also, features like scaling, load balancing and DNS, which i highlighted before,
are accessible only in swarm mode.
We have to access target server via SSH and change it's mode to swarm:
docker swarm init
This command also prints tokens which can be used later from other servers to join the swarm by using
docker swarm join --token xxx
command.
But in this article, we only have one server and we are not going to use docker swarm join
.
We are going to use remote connection from Gitlab CI to our docker service on target server.
So we are changing docker service configuration to make docker service remotely accessible.
To do this create/change docker
service configuration for systemd
:
sudo -s mkdir -p /etc/systemd/system/docker.service.d touch /etc/systemd/system/docker.service.d/startup_options.conf
startup_options.conf contents:
[Service] ExecStart=/usr/bin/dockerd -H fd:// -H tcp://0.0.0.0:2376
Restart systemd and docker service:
systemctl daemon-reload
Now docker service is remotely accessible.
deploy_docker_stage: environment: name: stage url: https://someurl image: docker:19.03.1 services: — docker:19.03.1-dind stage: deploy variables: DOCKER_HOST: "tcp://${DOCKER_HOST}:2376" before_script: — apk add jq — docker login -u $USER -p $PASSWORD $DOCKER_REPO script: - export CONFIG=$(echo $CONFIG1_STAGE | jq -c) && docker stack deploy --with-registry-auth -c ./docker/stage/app.yml app
We changed the DOCKER_HOST
varaible to make docker
command access our remote
server which we configured previously.
Our image is stored in private repository, to access which we used docker login
command.
To make docker stack deploy
command use authorization granted by docker login
,
--with-registry-auth
parameter is set.
yaml configuration file ./docker/stage/app.yml
contents:
version: '3.8' services: app: image: ${DOCKER_REPO}/${DOCKER_IMAGE} environment: — CONFIG ports: — "9091:9091" — "8444:8444" depends_on: — postgres — redis deploy: replicas: 3 update_config: parallelism: 2 delay: 3s order: start-first failure_action: rollback monitor: 1m restart_policy: max_attempts: 3 # ... other services
docker stack deploy
is very helpful because it uses
environment variables to fill the configuration.
We use ${DOCKER_REPO}
, ${DOCKER_IMAGE}
и CONFIG
.
Deploy structure in yaml sets up deployment:
order: start-first
makes new container start before old container is stopped
which makes our deploy downtime-less.parallelism: 2
sets how many container pairs are going
to be updated in one time, which affect on server load during the update.monitor: 1m
sets the time which docker service will monitor
new containers to make decision if update is successful.failure_action: rollback
sets behaviour if one of
new containers is failed — rollback is chosen.