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
2. ‘Service’ part
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
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 stackcommand accepts only pre-built images.
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
Alternative Dockerfile, it is used as an image.
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
ARGis not available in the build instructions under from.
If want an argument available in both placces, specify it under
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 (
off) must be enclosed in quotes
This option can not found in our files, so just explain normally.
build: context: . cache_from: - alpine:latest - corp/web_app:3.14
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 is
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"
Config on per-service basis using per-service
config . Two different syntax variants are supported.
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
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.
gid: The numeric UID or GID that owns the mounted config file within in the service’s task containers. Both default to
0on 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,
0444represents world-readable. The default is
0444. 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
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
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
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
mydata. Also one bind type volume for saving nginx log.
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"
The long form syntax allows the configuration of additional fields that can’t be expressed in the short form.
target: the port inside the container
published: the publicly exposed port
protocol: the port protocol (
hostfor publishing a host port on each node, or
ingressfor a swarm mode port to be load balanced.
ports: - target: 80 published: 8080 protocol: tcp mode: host
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
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
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
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 of
monitor: Duration after each task update to monitor for failure
max_failure_ratio: Failure rate to tolerate during an update.
order: Order of operations during updates. One of
stop-first(old task is stopped before starting new one), or
start-first(new task is started first, and the running tasks briefly overlap) (default
stop-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
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