Small knowledge, big challenge! This article is participating in the creation activity of “Essential Tips for Programmers”.

This article has participated in the “Digitalstar Project” and won a creative gift package to challenge the creative incentive money.

Docker advanced | Docker Compose

background

Previously through DockerFile using Docker Build command to generate images through Docker Run, are manually to operate and is a single container. If there are 100 microservices and they all have dependencies, how do we maintain them? Docker Compose makes it easy and efficient to manage containers. Defining and running multiple containers

The official introduction

  • Compose is a program that defines and runs multiple containers.

  • The Yaml File configuration file is required

  • Single command command

Compose is a tool for defining and running multi-container Docker applications. With Compose, you use a YAML file to configure your application’s services. Then, with a single command, you create and start all the services from your configuration. To learn more about all the features of Compose, see the list of features.

Docker Compose is available for all environments

Compose works in all environments: production, staging, development, testing, as well as CI workflows. You can learn more about each case in Common Use Cases.

Using the step

Using Compose is basically a three-step process:

  1. Define your app’s environment with a Dockerfile so it can be reproduced anywhere.
    • Dockerfile ensures that our project can run anywhere
  2. Define the services that make up your app in docker-compose.yml so they can be run together in an isolated environment.
    • What is a service?

    • Docker-comemage. yml docker-comemage. yml

  3. Run docker compose up and the Docker compose command starts and runs your entire app. You can alternatively run docker-compose up using the docker-compose binary.
    • Start the project

Purpose: Batch container orchestration.

Compose is an official Docker open source project, a standalone project that requires installation

Dockerfile lets programs run anywhere. For Web services, redis,mysql,nginx, multiple containers, we can write a Compose file and bundle these services in bulk

docker-compose.yml

version: "3.9"  # optional since v1.27.0
services:
  web:
    build: .
    ports:
      - "5000:5000"
    volumes:
      - .:/code
      - logvolume01:/var/log
    links:
      - redis
  redis:
    image: redis
volumes:
  logvolume01: {}
Copy the code

Docker-compose up brings all services online in one click

Compose: important concept

  • Compose is used for orchestration of services, applications (Web, Redis,mysql)
  • The project of the project. An associated set of containers

The installation

  1. download

    sudo curl -L "https://github.com/docker/compose/releases/download/1.29.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
    
    # backup address: domestic mirror
    sudo curl -L "https://get.daocloud.io/docker/compose/releases/download/1.29.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 100 423 100 423 00 177 0 0:00:02 0:00:02 --:--:-- 177 100 12.1m 100 12.1m 00 3832K 0 0:00:03 0:00:03 --:--:-- 31.4m# View download results
    $ cd /usr/local/bin
    
    [root@VM-8-10-centos ~]# cd /usr/local/bin
    [root@VM-8-10-centos bin]# ll12476-rwxr-xr-x 1 root root 383 12月 10 2019 chardetect-rwxr-xr-x 1 root root 389 12月 10 2019 cloud-init-rwxr-xr-x 1 root root 1781 12月 10 2019 cloud-init-per-rw-r --r-- 1 root root 12737304 10月 1 14:26 docker-compose# Download successful
    Copy the code
  2. authorization

    $ sudo chmod +x /usr/local/bin/docker-compose # authorization
    $ docker-compose version Test the installation resultsDocker-compose version 1.29.2, build 5becea4C docker-py version: 5.0.0 CPython version: 3.7.10 OpenSSL version: OpenSSL 1.1.0L 10 Sep 2019# Install successfully
    Copy the code

experienceGet started

Python applications: counters, counting using Redis

1.Setup : Define the application dependencies

The dependency files needed to create the project ~

Create project storage directory
$ cd ~
$ mkdir app  
$ cd app
# Create project file Aki
$ mkdir composetest
$ cd composetest
# create app.py file
$ vim app.py  The source code is below
Create requirements. TXT to write the required dependencies for the project
$ vim  requirements.txt 
Copy the code

app.py

import time

import redis
from flask import Flask

app = Flask(__name__)
cache = redis.Redis(host='redis', port=6379)

def get_hit_count() :
    retries = 5
    while True:
        try:
            return cache.incr('hits')
        except redis.exceptions.ConnectionError as exc:
            if retries == 0:
                raise exc
            retries -= 1
            time.sleep(0.5)

@app.route('/')
def hello() :
    count = get_hit_count()
    return 'Hello World! I have been seen {} times.\n'.format(count)
Copy the code

requirements.txt

flask
redis
Copy the code

2.Create a Dockerfile

Create Dockerfile

$ vim Dockerfile
Copy the code

Dockerfile

# syntax=docker/dockerfile:1
FROM python:3.7-alpine
WORKDIR /code
ENV FLASK_APP=app.py
ENV FLASK_RUN_HOST=0.0.0.0
RUN apk add --no-cache gcc musl-dev linux-headers
COPY requirements.txt requirements.txt
RUN pip install -r requirements.txt
EXPOSE 5000
COPY.
CMD ["flask"."run"]
Copy the code

3.Define services in a Compose file

Define the service in Compose

vim docker-compose.yml
Copy the code

docker-compose.yml

version: "3.9"
services:
  web:
    build: .
    ports:
      - "5000:5000"
  redis:
    image: "redis:alpine"
Copy the code

4.Build and run your app with Compose

Build & Run our app

$ docker-compose up 
# or
$ docker-compose up -d  # background bootBuilding Web Sending build context to Docker Daemon 5.632kB Step 1/10: FROM python:3.7-alpine --> a436fb2c575c Step 2/10: WORKDIR /code --> Using cache --> 02545a7b7f7c Step 3/10: ENV FLASK_APP=app.py ---> Using cache ---> ed7fe3f6c9c6 Step 4/10 : ENV FLASK_RUN_HOST=0.0.0.0 --> Using cache --> 80ea3d59f3f4 Step 5/10: RUN apk add --no-cache gcc musl-dev linux-headers ---> RunninginD2e239100b80 fetch https://dl-cdn.alpinelinux.org/alpine/v3.14/main/x86_64/APKINDEX.tar.gz ^ CGracefully stopping... (press Ctrl+C again to force) [root@VM-8-10-centos composetest]# ^C
[root@VM-8-10-centos composetest]# clear

[root@VM-8-10-centos composetest]# sudo docker-compose up Sudo: docker-compose: command not found [root@VM-8-10-centos composetest]# su docker-compose up Su: docker-compose does not exist [root@VM-8-10-centos composetest]# docker-compose up Building Web Sending build context to Docker Daemon 5.632kB Step 1/10: FROM python:3.7-alpine --> a436fb2c575c Step 2/10: WORKDIR /code --> Using cache --> 02545a7b7f7c Step 3/10: ENV FLASK_APP=app.py ---> Using cache ---> ed7fe3f6c9c6 Step 4/10 : ENV FLASK_RUN_HOST=0.0.0.0 --> Using cache --> 80ea3d59f3f4 Step 5/10: RUN apk add --no-cache gcc musl-dev linux-headers ---> Runningin7 d9a832e54e3 fetch https://dl-cdn.alpinelinux.org/alpine/v3.14/main/x86_64/APKINDEX.tar.gz fetch https://dl-cdn.alpinelinux.org/alpine/v3.14/community/x86_64/APKINDEX.tar.gz (1/13) Installing libgcc (10.3.1_git20210424-r2) (2/13) Installing libstdc++ (10.3.1_git20210424-r2) (3/13) Installing binutils (2.35.2-r2) (4/13) Installing libgomp (10.3.1_GIT20210424-R2) (5/13) Installing libatomic (10.3.1_GIT20210424-R2) (6/13 Libgphobos (10.3.1_gIT20210424-R2) (7/13) Installing GMP (6.2.1-R0) (8/13) Installing ISL22 (0.22-R0) (9/13 Mpfr4 (4.1.0-R0) (10/13) Installing MPC1 (1.2.1-R0) (11/13) Installing GCC (10.3.1_GIT20210424-R2) (12/13) Linux-headers (5.10.41-R0) (13/13) Installing MUSl-dev (1.2.2-R3) Executing BUSyBOX-1.33.1-R3. Trigger OK: 140 MiBin 48 packages
Removing intermediate container 7d9a832e54e3
 ---> c6b8ad3388a1
Step 6/10 : COPY requirements.txt requirements.txt
 ---> b25eb321aea3
Step 7/10 : RUN pip install -r requirements.txt
 ---> Running inC9b03beaca70 Collecting Flask Downloading flask -2.0.1-Py3-None-any. WHL (94 kB) Collecting Redis Downloading Collecting Jinja2>= Downloading jinja2-3.0.1-py3-none-any. WHL (50 kB) Downloading jinja2-3.0.1-py3-none-any. WHL (50 kB) Downloading Jinja2-3.0.1-py3-none-any. WHL (50 kB) Downloading Jinja2-3.0.1-py3-none-any. WHL (50 kB) Downloading Jinja2-3.0.1-py3-none-any. WHL (50 kB) Collecting click>=7.1.2 Downloading click-8.0.1-py3-none-any. WHL (97 kB) Downloading Werkzeug>=2.0 Downloading Werkzeug-2.0.1-py3-none-any.whl (288 kB) Collecting itsDangerous >=2.0 Downloading itsDangerous-2.0.1-py3-none-any.whL (18 kB) Collecting importlib - metadata Downloading importlib_metadata 4.8.1 - py3 - none - any. WHL (17 kB) Collecting MarkupSafe>=2.0 Downloading Markupsafe-2.0.1.tar. gz (18 kB) Collecting typing-Extensions >=3.6.4 Downloading Typing_extensions 3.10.0.2 - py3 - none - any. WHL (26 kB) Collecting zipp > = 0.5 Downloading zipp 3.6.0 - py3 - none - any. WHL (5.3) kB) Building wheelsfor collected packages: MarkupSafe
  Building wheel for MarkupSafe (setup.py): started
  Building wheel for MarkupSafe (setup.py): finished with status 'done'
  Created wheel forMarkupSafe: Filename = MarkupSafe - 2.0.1 cp37 - cp37m - linux_x86_64. WHL size = 14616 sha256=a2be1498a2fa606910a87342770f0f777eb9ce4a73a209969fbded2bfb5bd0b5 Storedindirectory: /root/.cache/pip/wheels/1a/18/04/e3b5bd888f000c2716bccc94a565239f9defc47ef93d9e7bea Successfully built MarkupSafe Installing collected packages: zipp, typing-extensions, MarkupSafe, importlib-metadata, Werkzeug, Jinja2, itsdangerous, click, redis, Flask Successfully installed jinjA2-3.0.1 markupsafe-2.0.1 werkzeug-2.0.1 click-8.0.1 flask-2.0.1 Importlib-metadata-4.8.1 itsDangerous -2.0.1 redis-3.5.3 typing-extensions-3.10.0.2 zipp-3.6.0 WARNING: Running pip as the'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv
Removing intermediate container c9b03beaca70
 ---> 6ca85fbb3685
Step 8/10 : EXPOSE 5000
 ---> Running in 58a8698ea25a
Removing intermediate container 58a8698ea25a
 ---> 313ecb8fbfbd
Step 9/10 : COPY . .
 ---> 11705881d5c4
Step 10/10 : CMD ["flask"."run"]
 ---> Running ine2c0d681ab04 Removing intermediate container e2c0d681ab04 ---> e1a776378e7e Successfully built e1a776378e7e Successfully  tagged composetest_web:latest WARNING: Imagefor service web was built because it did not already exist. To rebuild this image you must use `docker-compose build` or `docker-compose up --build`.
Pulling redis (redis:alpine)...
alpine: Pulling from library/redis
a0d0a0d46f8b: Already exists
a04b0375051e: Pull complete
cdc2bb0f9590: Pull complete
8f19735ec10c: Pull complete
ac5156a4c6ca: Pull complete
7b7e1b3fdb00: Pull complete
Digest: sha256:fa785f9bd167b94a6b30210ae32422469f4b0f805f4df12733c2f177f500d1ba
Status: Downloaded newer image for redis:alpine
Creating composetest_web_1   ... done
Creating composetest_redis_1 ... doneAttaching to composetest_redis_1, composetest_web_1 redis_1 | 1: C 06:59:57 of the Oct 11th, 2021. 739# oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0OoRedis_1 | 1: C 06:59:57 of the Oct 11th, 2021. 739# Redis version=6.2.5, bits=64, commit=00000000, Modified =0, PID =1, just startedRedis_1 | 1: C 06:59:57 of the Oct 11th, 2021. 739# Warning: no config file specified, using the default config. In order to specify a config file use redis-server /path/to/redis.confRedis_1 | 1: M 06:59:57 of the Oct 11th, 2021. 740 * monotonic clock: POSIX clock_gettime redis_1 | 1: M 06:59:57 of the Oct 11th, 2021. 741 * Running mode = standalone, Port = 6379. Redis_1 | 1: M 06:59:57 of the Oct 11th, 2021. 741# WARNING: The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128.Redis_1 | 1: M 06:59:57 of the Oct 11th, 2021. 741# Server initializedRedis_1 | 1: M 06:59:57 of the Oct 11th, 2021. 741# WARNING overcommit_memory is set to 0! Background save may fail under low memory condition. To fix this issue add 'vm.overcommit_memory = 1' to /etc/sysctl.conf and then reboot or run the command 'sysctl vm.overcommit_memory=1' for this to take effect.Redis_1 | 1: M 06:59:57 of the Oct 11th, 2021. 741 * Ready to accept connections web_1 | * Serving Flask app'app.py' (lazy loading)
web_1    |  * Environment: production
web_1    |    WARNING: This is a development server. Do not use it in a production deployment.
web_1    |    Use a production WSGI server instead.
web_1    |  * Debug mode: off
web_1    |  * Running on all addresses.
web_1    |    WARNING: This is a development server. Do not use it inA production deployment. Web_1 | * Running on http://172.19.0.3:5000/ (Press CTRL + C to quit)# Startup succeeded
Copy the code

[root@VM-8-10-centos composetest]# curl localhost:5000
Hello World! I have been seen 2 times.
[root@VM-8-10-centos composetest]# curl localhost:5000
Hello World! I have been seen 3 times.
[root@VM-8-10-centos composetest]# curl localhost:5000
Hello World! I have been seen 4 times.
[root@VM-8-10-centos composetest]# curl localhost:5000
Hello World! I have been seen 5 times.
[root@VM-8-10-centos composetest]# curl localhost:5000
Hello World! I have been seen 6 times.
[root@VM-8-10-centos composetest]# curl localhost:5000
Hello World! I have been seen 7 times.
Copy the code

conclusion

  • Prepare the app app.py
  • Dockerfile applications are packaged as images
  • Docker-compose YAMl defines the entire service, required for the environment
  • Start the Compose projectdocker-compose up

process

  • Create a network
  • Perform Docker – compose – yml
  • Start all services
$ ls
# Prepared documents
app.py  docker-compose.yml  Dockerfile  requirements.txt
Copy the code

The rules

  1. Docker Images automatically downloads all dependent images
[root@VM-8-10-centos composetest]# docker imagesREPOSITORY TAG IMAGE ID CREATED SIZE composetest_Web latest e1a776378e7e 11 minutes ago 184MB Python 3.7-alpine A436fb2c575c 3 weeks ago 41.9MB Redis 5.0.9- AlPINE3.11 3661C84EE9d0 17 months ago 29.8MBCopy the code
  1. Docker Service is not currently in service
[root@VM-8-10-centos composetest]# docker ps
CONTAINER ID   IMAGE             COMMAND                  CREATED          STATUS         PORTS                                       NAMES
52a3bb4546dd   redis:alpine      "Docker - entrypoint. S..."   14 minutes ago   Up 3 minutes   6379/tcp                                    composetest_redis_1
480ad107851f   composetest_web   "flask run"14 minutes ago Up 3 minutes 0.0.0.0:5000->5000/ TCP, :::5000->5000/tcp composetest_web_1 [root@VM-8-10-centos composetest]# docker service ls #
Error response from daemon: This node is not a swarm manager. Use "docker swarm init" or "docker swarm join" to connect this node to swarm and try again.
Copy the code

Default service name filename _ service name _ _num, for example, composetest_web_1

_num indicates the number of replicas, which is used in cluster status

  1. Network rules

    $ docker network ls
    [root@VM-8-10-centos composetest]# docker network ls
    NETWORK ID     NAME                  DRIVER    SCOPE
    acaeca217cc5   bridge                bridge    local
    152181e8650e   composetest_default   bridge    local
    3edbb9cd9ab0   host                  host      local
    dad0ff6720e0   none                  null      local
    Copy the code

    Automatically creates a network composetest_default for us

    The content in the project is all under the same network, and they can all be accessed by domain name

    mysql:3360

    Viewing Network Details

    $ docker network inspect composetest_default
    
    "Containers": {
                "480ad107851fc859c79497f95999b917fbfd75e28ec8994f019a740f74798580": {
                    "Name": "composetest_web_1"."EndpointID": "48252e19ea813a665fdbac7ff456bf893350e5f48b2452de7d3c2b4fe8f867ae"."MacAddress": "02:42:ac:13:00:02"."IPv4Address": "172.19.0.2/16"."IPv6Address": ""
                },
                "52a3bb4546dd6526ff7e0fe11e2c0b33bd1efa8516da353845f84520d45e355f": {
                    "Name": "composetest_redis_1"."EndpointID": "15ddf67cbbdbbad1fc922142a66ef9dfb302ed8a4ba65ad2d8b068228d512015"."MacAddress": "02:42:ac:13:00:03"."IPv4Address": "172.19.0.3/16"."IPv6Address": ""}},Copy the code

    If we are in the same network, we can directly access through the domain name. Ensure high availability.

stop

Enter the project file
$ docker-compose down Use Ctrl+ C for default startup without -d
Copy the code

Docker-compose can now write a yamL configuration file for docker-compose up, which can start and stop all services in one click

conclusion

  1. Docker image. The Run = > container
  2. DockerFile build image => Service package
  3. Docker-compose startup project => Orchestrate multiple microservices/environments
  4. Docker network