首页 > 其他分享 >【Docker】Docker Compose服务依赖与健康检查

【Docker】Docker Compose服务依赖与健康检查

时间:2023-10-30 16:32:59浏览次数:32  
标签:REDIS Compose flask demo redis server 健康检查 Docker docker


【Docker】Docker Compose服务依赖与健康检查_1024程序员节

docker compose环境变量

为增加安全性,在前面的python例子中增加redis的密码校验,密码从环境变量中获取:

from flask import Flask
from redis import StrictRedis
import os
import socket

app = Flask(__name__)
redis = StrictRedis(host=os.environ.get('REDIS_HOST', '127.0.0.1'),
                    port=6379, password=os.environ.get('REDIS_PASS'))

@app.route('/')
def hello():
    redis.incr('hits')
    return f"Hello Container World! I have been seen {redis.get('hits').decode('utf-8')} times and my hostname is {socket.gethostname()}.\n"

对前面的docker-compose.yml进行修改如下:

version: "3.3"

services:
  flask-demo:
    build:
        context: .
        dockerfile: Dockerfile
    image: flask-demo:latest
    environment:
      - REDIS_HOST=redis-server
      - REDIS_PASS=${REDIS_PASSWORD}
    networks:
      - demo-network
    ports:
      - 8080:5000

  redis-server:
    image: redis:latest
    command: redis-server --requirepass ${REDIS_PASSWORD}
    networks:
     - demo-network

networks:
  demo-network:

在工程目录下新建.env文件,将环境变量配置好:

REDIS_PASS=abc

启动服务:

$ docker-compose up -d
Creating network "app3_demo-network" with the default driver
Creating app3_redis-server_1 ... done
Creating app3_flask-demo_1   ... done

参考文档:https://docs.docker.com/compose/environment-variables/

docker compose健康检查

Dockerfile healthcheck: https://docs.docker.com/engine/reference/builder/#healthcheck

docker compose:https://docs.docker.com/compose/compose-file/compose-file-v3/#healthcheck

健康检查是容器运行状态的高级检查,主要是检查容器所运行的进程是否能正常的对外提供“服务”,比如一个数据库容器,我们不光需要这个容器是up的状态,我们还要求这个容器的数据库进程能够正常对外提供服务,这就是所谓的健康检查。

容器的健康检查

容器本身有一个健康检查的功能,但是需要在Dockerfile里定义,或者在执行docker container run的时候,通过下面的一些参数指定:

--health-cmd string              Command to run to check health
--health-interval duration       Time between running the check
                                (ms|s|m|h) (default 0s)
--health-retries int             Consecutive failures needed to
                                report unhealthy
--health-start-period duration   Start period for the container to
                                initialize before starting
                                health-retries countdown
                                (ms|s|m|h) (default 0s)
--health-timeout duration        Maximum time to allow one check to

下面我们对前面的flask例子增加健康检查,主要是在Dockerfile中增加HEALTHCHECK指令:

FROM python:3.9.5-slim

RUN pip install flask redis && \
    apt-get update && \
    apt-get install -y curl && \
    groupadd -r flask && useradd -r -g flask flask && \
    mkdir /src && \
    chown -R flask:flask /src

USER flask

COPY app.py /src/app.py

WORKDIR /src

ENV FLASK_APP=app.py REDIS_HOST=redis

EXPOSE 5000

HEALTHCHECK --interval=30s --timeout=3s \
    CMD curl -f http://localhost:5000/ || exit 1

CMD ["flask", "run", "-h", "0.0.0.0"]

上面Dockerfili里的HEALTHCHECK就是定义了一个健康检查。会每隔30秒检查一次,如果失败就会退出,退出代码是1。

构建flask-demo镜像,并启动容器:

$ docker build -t flask-demo .

$ docker network create mynetwork
b3958a0cb961ddcc856c7e0458bc10489c456727f6061d1f9dc23e7e264741ae

$ docker container run --rm -d --name flask-demo --network=mynetwork --env REDIS_PASS=abc --env REDIS_HOST=redis flask-demo
e761d19949b9e3284471864101ec196807fc6145431903f4041e04daf950fa86

$ docker container ps
CONTAINER ID   IMAGE        COMMAND                  CREATED         STATUS                            PORTS      NAMES
e761d19949b9   flask-demo   "flask run -h 0.0.0.0"   8 seconds ago   Up 8 seconds (health: starting)   5000/tcp   flask-demo

启动容器后查看容器状态未health: starting

因为此时没有启动redis服务,所以无法访问http://localhost:5000/,经过3次检查后发现一直是不通的,然后health的状态会从starting变为unhealthy:

$ docker container ps
CONTAINER ID   IMAGE        COMMAND                  CREATED         STATUS                     PORTS      NAMES
e761d19949b9   flask-demo   "flask run -h 0.0.0.0"   2 minutes ago   Up 2 minutes (unhealthy)   5000/tcp   flask-demo

也可以通过docker container inspect查看其中有关health的详情:

"Health": {
    "Status": "unhealthy",
    "FailingStreak": 4,
    "Log": [
        {
            "Start": "2023-10-09T14:17:51.7014803+08:00",
            "End": "2023-10-09T14:17:54.7023591+08:00",
            "ExitCode": -1,
            "Output": "Health check exceeded timeout (3s)"
        },
        {
            "Start": "2023-10-09T14:18:24.7095286+08:00",
            "End": "2023-10-09T14:18:27.7099692+08:00",
            "ExitCode": -1,
            "Output": "Health check exceeded timeout (3s)"
        },
        {
            "Start": "2023-10-09T14:18:57.7264309+08:00",
            "End": "2023-10-09T14:19:00.7267289+08:00",
            "ExitCode": -1,
            "Output": "Health check exceeded timeout (3s)"
        },
        {
            "Start": "2023-10-09T14:19:30.7443718+08:00",
            "End": "2023-10-09T14:19:33.7444952+08:00",
            "ExitCode": -1,
            "Output": "Health check exceeded timeout (3s)"
        }
    ]
}

此时再启动redis服务,注意设置访问redis的密码:

$ docker container run --rm -d --network=mynetwork --name redis redis redis-server --requirepass abc
985cd32adbffd0d631a5a193c25903d704ddf08fb9a06f65a8e05af601a2ad77

$ docker container ps
CONTAINER ID   IMAGE        COMMAND                  CREATED              STATUS                   PORTS      NAMES
985cd32adbff   redis        "docker-entrypoint.s…"   About a minute ago   Up About a minute        6379/tcp   redis
e761d19949b9   flask-demo   "flask run -h 0.0.0.0"   8 minutes ago        Up 8 minutes (healthy)   5000/tcp   flask-demo

经过几秒钟,我们的flask-demo变成了healthy。

docker-compose健康检查

在上面的例子基础上删除Dockerfile中的心跳检测。

在docker-compose.yml中增加健康检查的配置:

version: "3.8"

services:
  flask-demo:
    build:
        context: .
        dockerfile: Dockerfile
    image: flask-demo:latest
    environment:
      - REDIS_HOST=redis-server
      - REDIS_PASS=${REDIS_PASS}
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:5000"]
      interval: 30s
      timeout: 3s
      retries: 3
      start_period: 40s
    networks:
      - demo-network
    ports:
      - 8080:5000

  redis-server:
    image: redis:latest
    command: redis-server --requirepass ${REDIS_PASS}
    networks:
     - demo-network

networks:
  demo-network:

构建镜像并启动:

$ docker-compose up -d --build

$ docker-compose ps
       Name                      Command                  State                        Ports
--------------------------------------------------------------------------------------------------------------
app5_flask-demo_1     flask run -h 0.0.0.0             Up (healthy)   0.0.0.0:8080->5000/tcp,:::8080->5000/tcp
app5_redis-server_1   docker-entrypoint.sh redis ...   Up             6379/tcp

可以通过修改docker-compose.yml文件中密码来测试容器状态为Up (unhealthy)的情况。

docker compose服务依赖

如果服务之间的启动有依赖顺序,可以使用depends_on来配置。

version: "3.8"

services:
  flask-demo:
    build:
        context: .
        dockerfile: Dockerfile
    image: flask-demo:latest
    environment:
      - REDIS_HOST=redis-server
      - REDIS_PASS=${REDIS_PASS}
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:5000"]
      interval: 30s
      timeout: 3s
      retries: 3
      start_period: 40s
    depends_on:
      - redis-server
    networks:
      - demo-network
    ports:
      - 8080:5000

  redis-server:
    image: redis:latest
    command: redis-server --requirepass ${REDIS_PASS}
    networks:
     - demo-network

networks:
  demo-network:

上面的例子配置了flask-demo依赖redis-server,在启动的时候会先启动redis-server,然后在启动flask-demo

$ docker-compose up -d
Creating network "app6_demo-network" with the default driver
Creating app6_redis-server_1 ... done
Creating app6_flask-demo_1   ... done

服务依赖与健康检查的结合

这里再引入nginx来更好的演示服务依赖与健康检查的结合。

version: "3.8"

services:
  flask-demo:
    build:
        context: .
        dockerfile: Dockerfile
    image: flask-demo:latest
    environment:
      - REDIS_HOST=redis-server
      - REDIS_PASS=${REDIS_PASS}
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:5000"]
      interval: 30s
      timeout: 3s
      retries: 3
      start_period: 40s
    depends_on:
      - redis-server
    networks:
      - backend
      - frontend

  redis-server:
    image: redis:latest
    command: redis-server --requirepass ${REDIS_PASS}
    networks:
      - backend
  nginx:
    image: nginx:stable-alpine
    ports:
      - 8000:80
    depends_on:
      flask-demo:
        condition: service_healthy
    volumes:
      - ./nginx.conf:/etc/nginx/conf.d/default.conf:ro
      - ./log/nginx:/var/log/nginx
    networks:
      - frontend

networks:
  backend:
  frontend:

nginx.conf文件的内容如下:

server {
  listen  80 default_server;
  location / {
    proxy_pass http://flask-demo:5000;
  }
}

启动服务,可以发现nginxflask-demo启动后并健康检查通过后才启动。

$ docker-compose up -d
Creating network "app7_backend" with the default driver
Creating network "app7_frontend" with the default driver
Creating app7_redis-server_1 ... done
Creating app7_flask-demo_1   ... done
Creating app7_nginx_1        ... done

$ docker-compose ps
       Name                      Command                  State                      Ports
----------------------------------------------------------------------------------------------------------
app7_flask-demo_1     flask run -h 0.0.0.0             Up (healthy)   5000/tcp
app7_nginx_1          /docker-entrypoint.sh ngin ...   Up             0.0.0.0:8000->80/tcp,:::8000->80/tcp
app7_redis-server_1   docker-entrypoint.sh redis ...   Up             6379/tcp


标签:REDIS,Compose,flask,demo,redis,server,健康检查,Docker,docker
From: https://blog.51cto.com/morris131/8094087

相关文章

  • 【Docker】Docker数据的存储
    默认情况下,在运行中的容器里创建的文件,被保存在一个可写的容器层里,如果容器被删除了,则对应的数据也随之删除了。这个可写的容器层是和特定的容器绑定的,也就是这些数据无法方便的和其它容器共享。Docker主要提供了两种方式做数据的持久化:DataVolume:由Docker管理(数据目录/var/lib/d......
  • 【Docker】Docker的网络
    Docker提供了多种内置的网络模式,用于在容器之间建立网络连接。这些网络模式,包括桥接网络、主机网络、无网络模式。我们将主要探讨每种网络模式的优缺点、适用场景。桥接网络桥接网络是Docker的默认网络模式。在桥接网络中,Docker会为每个容器创建一个虚拟网络接口,并为容器分配一个IP......
  • 【Docker】Docker Compose的使用
    我们知道使用一个Dockerfile模板文件,可以让用户很方便的定义⼀个单独的应用容器。然而,在日常工作中,经常会碰到需要多个容器相互配合来完成某项任务的情况。例如要实现一个Web项目,除了Web服务容器本身,往往还需要再加上后端的数据库服务容器,甚至还包括负载均衡容器等,我们只能一个一个......
  • docker指令详解
    Docker指令详解1.生命周期管理run创建并运行容器,格式dockerrun[OPTIONS]image[COMMAND][ARG...],参数说明dockerrun[options]image[command][arg...]-d,--detach#后台运行-it,--interacticetty#交互终端形式运行-p,--publishlist#指定端口-v,--vo......
  • docker 中 centos7
     >dockerrun-itd--namecentos_7centos:7/bin/bashdockerrun:启动一个容器没有就新创建-itd: -i保持STDIN打开允许你输入到容器中进行-t为容器分配一个伪终端-d容器在后台运行--name:指定容器的名称centos:7镜像的名称 基于这个镜像搞的容器/bin/bash :......
  • Docker Swarm 节点维护
    DockerSwarmModeDockerSwarm集群搭建DockerSwarm节点维护DockerService创建1.角色转换Swarm集群中节点的角色只有manager与worker,所以其角色也只是在manager与worker间的转换。即worker升级为manager,或manager降级为worker。1.1worker升级为manager在manag......
  • Docker Service 创建
    DockerSwarmModeDockerSwarm集群搭建DockerSwarm节点维护DockerService创建service只能依附于dockerswarm集群,所以service的创建前提是,swarm集群搭建完毕。1.创建servicedockerservicecreate命令用于创建service,需要在manager中运行。与创建容器的命令dock......
  • Docker 资源限制
    Docker资源限制1、内存限制#Docker提供的内存限制功能有以下几点: -容器能使用的内存和交换区的大小 -容器的核心内存大小 -容器虚拟内存的交换行为 -容器内存的软性限制 -是否杀死占用过多内存的容器 -容器被杀死的优先级内存限制相关参数执行dockerrun命令......
  • Docker安装
    Docker安装1.卸载旧版dockeryumremovedocker\docker-client\docker-client-latest\docker-common\docker-latest\docker-latest-logrotate\docker-logrotate\docker-engine2.配置Docker的yum库安装yum工具yuminstall-yyum......
  • docker
    Docker目录Docker1安装镜像和容器命令解读2docker基础常见命令命令别名数据卷本地目录挂载镜像Dockerfiledocker网络3项目部署DockerCompose1安装参考:⁤⁤‌‍⁢⁡⁤‬⁡‬‌⁡⁢⁣‬⁡‌⁣‌⁤⁡‌⁣‍⁢⁤⁣⁣⁢‍‍⁡⁣⁣‬‍⁢⁣‌⁡Linux环境搭建-飞书云文档(feishu.......