How to depoly docker image to server, based on constructed CI/CD pipeline? This article is about the specific steps and details on it.
1. Example Code
There are several versions of Conpose file: 1,2, 2,x and 3.x. Here is example code on official website based on version 3.7 on Yaml.
version: "3.7"
services:
redis:
image: redis:alpine
ports:
- "6379"
networks:
- frontend
deploy:
replicas: 2
update_config:
parallelism: 2
delay: 10s
restart_policy:
condition: on-failure
db:
image: postgres:9.4
volumes:
- db-data:/var/lib/postgresql/data
networks:
- backend
deploy:
placement:
constraints: [node.role == manager]
vote:
image: dockersamples/examplevotingapp_vote:before
ports:
- "5000:80"
networks:
- frontend
depends_on:
- redis
deploy:
replicas: 2
update_config:
parallelism: 2
restart_policy:
condition: on-failure
result:
image: dockersamples/examplevotingapp_result:before
ports:
- "5001:80"
networks:
- backend
depends_on:
- db
deploy:
replicas: 1
update_config:
parallelism: 2
delay: 10s
restart_policy:
condition: on-failure
worker:
image: dockersamples/examplevotingapp_worker
networks:
- frontend
- backend
deploy:
mode: replicated
replicas: 1
labels: [APP=VOTING]
restart_policy:
condition: on-failure
delay: 10s
max_attempts: 3
window: 120s
placement:
constraints: [node.role == manager]
visualizer:
image: dockersamples/visualizer:stable
ports:
- "8080:8080"
stop_grace_period: 1m30s
volumes:
- "/var/run/docker.sock:/var/run/docker.sock"
deploy:
placement:
constraints: [node.role == manager]
networks:
frontend:
backend:
volumes:
db-data:
Now I will explain details of the config file.
This file is defined into 3 big parts, services, networks and volumns.
A service defination contains configuration that is appiled to each container ,and start for that service So pass command-line parameters to
docker container create
. Likewise, if you want to define network or volume, can use command like docker network create
or docker volume create
.
Also can use environment variables in configurations like {VARIABLE}
syntax.
2. ‘Service’ part
2.1 build
This part is for configurations applied at build time.
Build part can only specified by a path:
version: "3.7"
services:
webapp:
build: ./dir
Or with other specific configurations,like dockerfile and args:
version: "3.7"
services:
webapp:
build:
context: ./dir
dockerfile: Dockerfile-alternate
args:
buildno: 1
I will mention the args meaning below.
The args are under build
command, if specify image
as well as build
, then Compose specified image
,in the example below, it is webapp
with the option tag
. This result in an image named webapp
and tagged with tag
, built from ./dir
:
build: ./dir
image: webapp:tag
Note: This option is ignored when deploying a stack in swarm mode with a (version 3) Compose file. The
docker stack
command accepts only pre-built images.
2.2 Context
Can be a path to directory containing a Dockerfile, or a url to git repository.
Compose builds and tags it with a generated name
build:
context: ./dir
2.3 Dockerfile
Alternative Dockerfile, it is used as an image.
2.4 Args
First specify arguments in Dockerfile:
ARG buildno
ARG gitcommithash
RUN echo "Build number: $buildno"
RUN echo "Based on commit: $gitcommithash"
Args can be used in 2 ways, like below:
build:
context: .
args:
buildno: 1
gitcommithash: cdc3b19
build:
context: .
args:
- buildno=1
- gitcommithash=cdc3b19
Note: in Dockerfile, if specify
ARG
before theFROM
instruction,ARG
is not available in the build instructions under from.If want an argument available in both placces, specify it under
FROM
instruction.
Can omit the value when only specifying a building argument, in this case, at build time,its value is the value in environment where Compose is running.
args:
- buildno
- gitcommithash
YAML boolean values (
true
,false
,yes
,no
,on
,off
) must be enclosed in quotes
2.5 Cache_From
This option can not found in our files, so just explain normally.
build:
context: .
cache_from:
- alpine:latest
- corp/web_app:3.14
2.6 Labels
Add metadata using Docker Labels
.Can use it either an array or a dictionary.
Recommanded use Reverse-DNS notation to prevent labels from conflicting whit those used by other software.
Reverse-DNs notation: if your website is
example.com
, Reverse-DNS iscom.example
build:
context: .
labels:
com.example.description: "Accounting webapp"
com.example.department: "Finance"
com.example.label-with-empty-value: ""
build:
context: .
labels:
- "com.example.description=Accounting webapp"
- "com.example.department=Finance"
- "com.example.label-with-empty-value"
2.7 Configs
Config on per-service basis using per-service config
. Two different syntax variants are supported.
Short syntax
Short syntax only specify the config name.
Code below define my_other_config as an external resource,which means it has already been defined in Docker, either by running the docker config create
command or by another stack deployment.
If the external config does not exist, the stack deployment fails with config not found
error.
version: "3.7"
services:
redis:
image: redis:latest
deploy:
replicas: 1
configs:
- my_config
- my_other_config
configs:
my_config:
file: ./my_config.txt
my_other_config:
external: true
Long Syntax
In this format, can define more details on deployment
source
: The name of the config as it exists in Docker.target
: The path and name of the file to be mounted in the service’s task containers. Defaults to/
if not specified.uid
andgid
: The numeric UID or GID that owns the mounted config file within in the service’s task containers. Both default to0
on Linux if not specified. Not supported on Windows.mode
: The permissions for the file that is mounted within the service’s task containers, in octal notation. For instance,0444
represents world-readable. The default is0444
. Configs cannot be writable because they are mounted in a temporary filesystem, so if you set the writable bit, it is ignored. The executable bit can be set. If you aren’t familiar with UNIX file permission modes, you may find this permissions calculator useful.
version: "3.7"
services:
redis:
image: redis:latest
deploy:
replicas: 1
configs:
- source: my_config
target: /redis_config
uid: '103'
gid: '103'
mode: 0440
configs:
my_config:
file: ./my_config.txt
my_other_config:
external: true
2.8 Image
Specify the image to start container from. Can either be a repository/tag or a partial image ID.
image: redis
image: ubuntu:14.04
image: tutum/influxdb
image: example-registry.com:4000/postgresql
image: a4bc65fd
2.9 Environment
Add environment variables. Can use either an array or a dictionary.
environment:
RACK_ENV: development
SHOW: 'true'
SESSION_SECRET:
environment:
- RACK_ENV=development
- SHOW=true
- SESSION_SECRET
2.10 Volumes
volume is the way for containers to process persistent data. In compose, we can use 2 ways to specify Volume:
- Use named volume
- Use path in host to create volumes
version: "3.2"
services:
web:
image: nginx:alpine
volumes:
- type: volume
source: mydata
target: /data
- type: bind
source: ./nginx/logs
target: /var/log/nginx
jenkins:
image: jenkins/jenkins:lts
volumes:
- jenkins_home:/var/jenkins_home
- mydata:/data
volumes:
mydata:
jenkins_home:
In this config file, we create 3 volumes together, 2 are named volumes Jenkins_home
and mydata
. Also one bind type volume for saving nginx log.
2.11 Ports
Expose ports.
Short Syntax
ports:
- "3000"
- "3000-3005"
- "8000:8000"
- "9090-9091:8080-8081"
- "49100:22"
- "127.0.0.1:8001:8001"
- "127.0.0.1:5000-5010:5000-5010"
- "6060:6060/udp"
Long Syntax
The long form syntax allows the configuration of additional fields that can’t be expressed in the short form.
target
: the port inside the containerpublished
: the publicly exposed portprotocol
: the port protocol (tcp
orudp
)mode
:host
for publishing a host port on each node, oringress
for a swarm mode port to be load balanced.
ports:
- target: 80
published: 8080
protocol: tcp
mode: host
2.12 Deploy
Specify configuration related to the deployment and running of services.
Only take effect when deploying to a swarm with docker stack deploy, and is ignored by docker-compose up
and docker-compose run
Mode
Either global
(exactly one container per swarm node) or replicated
(a specified number of containers). The default is replicated
. (To learn more, see Replicated and global services in the swarm topics.)
version: "3.7"
services:
worker:
image: dockersamples/examplevotingapp_worker
deploy:
mode: global
Placement
Specify placement of constraints and preferences.
version: "3.7"
services:
db:
image: postgres
deploy:
placement:
constraints:
- node.role == manager
- engine.labels.operatingsystem == ubuntu 14.04
preferences:
- spread: node.labels.zone
Update_Config
Config how the service should be updated. useful for configuring rolling updates.
parallelism
: The number of containers to update at a time.delay
: The time to wait between updating a group of containers.failure_action
: What to do if an update fails. One ofcontinue
,rollback
, orpause
(default:pause
).monitor
: Duration after each task update to monitor for failure(ns|us|ms|s|m|h)
(default 0s).max_failure_ratio
: Failure rate to tolerate during an update.order
: Order of operations during updates. One ofstop-first
(old task is stopped before starting new one), orstart-first
(new task is started first, and the running tasks briefly overlap) (defaultstop-first
) Note: Only supported for v3.4 and higher.
version: "3.7"
services:
vote:
image: dockersamples/examplevotingapp_vote:before
depends_on:
- redis
deploy:
replicas: 2
update_config:
parallelism: 2
delay: 10s
order: stop-first
Healthcheck
Configure a check that’s run to determine whether or not containers for this service are “healthy”.
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost"]
interval: 1m30s
timeout: 10s
retries: 3
start_period: 40s