Docker

如何设置Docker container自动重启

 

零 问题痛点

之前运行好好的容器,因为意外情况如断电导致服务器重启之后,容器不会像我们期望的那样自动启动,导致容器提供的服务不可用,这时候需要人为介入去排查分析并手工启动容器。

那么,有没有比较优雅一点儿的方式,即使Docker服务需要被重启、服务器断电重启之后,Docker container可以自动启动,而不需要人为接管呢?

答案是:有。

 

一 问题原因

原因是我们的container在启动时,没有被加上—restart=always|unless-stopped等选项。也就意味着,容器一旦停止运行,无论什么原因造成它停止运行的,它就保持停止状态,不会自动重启。这是container的默认启动规则。

反之,如果container在启动时,有加上—restart=重启规则的选项的话,容器就会根据该重启规则来执行重启。

 

二 解决方案

具体处理起来得分两种情况:

  1. 如果container是通过docker命令创建并启动的,我们可以通过执行 docker update —restart=always|unless-stopped container_id|container_name,来修改容器的重启策略;
  2. 如果container是通过docker-compose创建并启动,除了要通过执行 docker update —restart=always|unless-stopped container_id|container_name,来修改容器的重启策略,还需要修改对应的docker-compose.yaml文件,并且执行docker-compose up -d来重启container;

💡 为什么需要执行docker-compose up -d来重启container? 因为,Docker compose的运行机制,是通过yaml文件的声明式配置来实现的。我们虽然手工修改了运行中的container,给它加上了—restart=always。为了防止,将来有人通过docker-compose up -d来更新发布启动该容器,导致重启策略被覆盖。所以,我们才执行这一步修改yaml文件,并重启容器。这在生产环境下需要斟酌考虑容器重启对业务的影响。

三 动手实践Docker容器置为自动重启

 

前两天周末,因为隔壁公司装修原因,导致机房线路被意外断电了。服务器断电重新启动之后,当前服务器上,Docker服务自动启动了,可是container没有启动:

[root@server ~]# docker ps -a
CONTAINER ID   IMAGE                           COMMAND                  CREATED       STATUS                      PORTS                                                      NAMES
7ee762685009   portainer/portainer-ce:latest   "/portainer"             2 years ago   Up 18 hours                 0.0.0.0:8000->8000/tcp, 0.0.0.0:9443->9443/tcp, 9000/tcp   portainer
7b91f981cd5c   nginx                           "/docker-entrypoint.…"   2 years ago   Exited (255) 18 hours ago   0.0.0.0:80->80/tcp, 0.0.0.0:2222->2222/tcp                 nginx-80
0990ea726eb7   redis                           "docker-entrypoint.s…"   3 years ago   Exited (255) 18 hours ago   0.0.0.0:6379->6379/tcp                                     redis-test
9488060c69b7   jira-agent-sso                  "/tini -- /entrypoin…"   4 years ago   Exited (255) 18 hours ago   0.0.0.0:8080->8080/tcp                                     celoan-jira
[root@server ~]# docker start celoan-jira
celoan-jira
[root@server ~]# docker start nginx-80
nginx-80
[root@server ~]# docker inspect nginx-80 --format='{{.HostConfig.RestartPolicy.Name}}'

[root@server ~]# docker inspect celoan-jira --format='{{.HostConfig.RestartPolicy.Name}}'

[root@server ~]# docker update --restart=always celoan-jira
celoan-jira
[root@server ~]# docker update --restart=always nginx-80
nginx-80
[root@server ~]# docker inspect celoan-jira --format='{{.HostConfig.RestartPolicy.Name}}'
always
[root@server ~]# docker inspect nginx-80 --format='{{.HostConfig.RestartPolicy.Name}}'
always
[root@server ~]# hostname -I
10.0.9.33 192.168.103.1 192.168.107.1 192.168.102.1 172.17.0.1 
[root@server ~]# 

 

需要手工执行,docker start xxxx;

有没有更优雅一点儿的方法呢?当服务器掉电重启之后,Docker服务自动启动之前,之前运行的container也会自动启动?

答案是有的。我们可以通过docker update —restart=always container-name|container-id

如上:docker update –restart=always celoan-jira

当然,在设置container自动重启之前,我们可以通过docker inspect container-name|container-id来查看该容器是否设置了自动重启。或者一步到位,通过执行

docker inspect container-name|container-id –format='{{.HostConfig.RestartPolicy.Name}}’

设置了container自动启动之后,我们可以再次通过该命令来校验设置是否生效。

 

此时,由于nginx-80和celoan-jira这2个container是通过docker-compose来启动并运行的,我们除了通过docker update —restart=always container-name|container-id修改了该container的重启策略之外,我们还得修改它的docker-compose.yaml文件,并且要执行docker-compose up -d;命令。

 

1 修改NGINX容器的docker-compose.yaml配置文件restart=always

修改之前:

[root@server nginx]# pwd
/root/docker/nginx
[root@server nginx]# ll
total 12
drwxr-xr-x. 2 root root 4096 Jan 12 09:44 conf.d
-rw-r--r--. 1 root root  557 May 29  2023 docker-compose.yaml
-rw-r--r--. 1 root root 1080 Oct 31  2023 nginx.conf
[root@server nginx]# cat docker-compose.yaml 
version: '2'
services:
  mysql:
    image: nginx
    container_name: nginx-80
    ports:
      - "80:80"
      - "2222:2222"
    volumes:
      - /root/docker/nginx/nginx.conf:/etc/nginx/nginx.conf
      - /root/docker/nginx/conf.d:/etc/nginx/conf.d
      - /root/prototype:/home/nginx/prototype
      - /data/prototype/web:/home/nginx/prototype-web
      - /home/nginx/web:/home/nginx/web
    networks:
      - nginx-network 
networks:
  nginx-network:
    driver: bridge
    ipam:
      driver: default
      config:
      - subnet: 192.168.102.0/24
    
[root@server nginx]#

 

修改之后:

[root@server nginx]# cat docker-compose.yaml 
version: '2'
services:
  mysql:
    image: nginx
    container_name: nginx-80
    ports:
      - "80:80"
      - "2222:2222"
    restart: always
    volumes:
      - /root/docker/nginx/nginx.conf:/etc/nginx/nginx.conf
      - /root/docker/nginx/conf.d:/etc/nginx/conf.d
      - /root/prototype:/home/nginx/prototype
      - /data/prototype/web:/home/nginx/prototype-web
      - /home/nginx/web:/home/nginx/web
    networks:
      - nginx-network 
networks:
  nginx-network:
    driver: bridge
    ipam:
      driver: default
      config:
      - subnet: 192.168.102.0/24
    
[root@server nginx]# 

 

执行docker compose up -d 使之生效

[root@server nginx]# ll
total 12
drwxr-xr-x. 2 root root 4096 Jan 12 09:44 conf.d
-rw-r--r--. 1 root root  577 Jan 30 05:57 docker-compose.yaml
-rw-r--r--. 1 root root 1080 Oct 31  2023 nginx.conf
[root@server nginx]# docker ps
CONTAINER ID   IMAGE                           COMMAND                  CREATED       STATUS      PORTS                                                      NAMES
7ee762685009   portainer/portainer-ce:latest   "/portainer"             2 years ago   Up 4 days   0.0.0.0:8000->8000/tcp, 0.0.0.0:9443->9443/tcp, 9000/tcp   portainer
7b91f981cd5c   nginx                           "/docker-entrypoint.…"   2 years ago   Up 3 days   0.0.0.0:80->80/tcp, 0.0.0.0:2222->2222/tcp                 nginx-80
9488060c69b7   jira-agent-sso                  "/tini -- /entrypoin…"   4 years ago   Up 3 days   0.0.0.0:8080->8080/tcp                                     celoan-jira
[root@server nginx]# docker-compose up -d
Recreating nginx-80 ... done
[root@server nginx]# docker ps
CONTAINER ID   IMAGE                           COMMAND                  CREATED         STATUS         PORTS                                                      NAMES
7d7384708862   nginx                           "/docker-entrypoint.…"   4 seconds ago   Up 3 seconds   0.0.0.0:80->80/tcp, 0.0.0.0:2222->2222/tcp                 nginx-80
7ee762685009   portainer/portainer-ce:latest   "/portainer"             2 years ago     Up 4 days      0.0.0.0:8000->8000/tcp, 0.0.0.0:9443->9443/tcp, 9000/tcp   portainer
9488060c69b7   jira-agent-sso                  "/tini -- /entrypoin…"   4 years ago     Up 3 days      0.0.0.0:8080->8080/tcp                                     celoan-jira
[root@server nginx]# 

 

 

2 处理celoan-jira容器的restart=always

修改之前:

[root@server jira]# pwd
/root/docker/jira
[root@server jira]# ll
total 16
-rw-r--r--. 1 root root  624 May 18  2021 crowd.properties
-rw-r--r--. 1 root root  700 May 18  2021 docker-compose.yml
-rw-r--r--. 1 root root 1940 Mar 22  2021 docker-compose.yml.bak
-rw-r--r--. 1 root root  255 May 18  2021 Dockerfile
[root@server jira]# cat docker-compose.yml
version: '2'
services:
  jira:
    image: jira-agent-sso
    container_name: celoan-jira
    environment:
      - JVM_MINIMUM_MEMORY=4096m
      - JVM_MAXIMUM_MEMORY=6144m
      - ATL_PROXY_NAME=jira.celoan.opt
      - ATL_PROXY_PORT=80
    ports:
      - "8080:8080"
    volumes:
      - /etc/localtime:/etc/localtime
      - /data/atlassian/jira-data:/var/atlassian/application-data/jira
    extra_hosts:
      - "jira.celoan.opt:10.0.9.33"
      - "wiki.celoan.opt:10.0.9.33"
      - "crowd.celoan.opt:10.0.9.33"
    networks:
      - celoan-atlassian-network
networks: 
  celoan-atlassian-network:
    driver: bridge
    ipam:
      driver: default
      config:
      - subnet: 192.168.107.0/24
[root@server jira]# 

 

修改之后,并docker-compose up -d使之生效:

如果docker-compose.yml配置文件,语法错误,导致不生效,docker-compose up -d会提示,并且不会重启容器:

[root@server jira]# ll
total 16
-rw-r--r--. 1 root root  624 May 18  2021 crowd.properties
-rw-r--r--. 1 root root  719 Jan 30 06:01 docker-compose.yml
-rw-r--r--. 1 root root 1940 Mar 22  2021 docker-compose.yml.bak
-rw-r--r--. 1 root root  255 May 18  2021 Dockerfile
[root@server jira]# cat docker-compose.yml
version: '2'
services:
  jira:
    image: jira-agent-sso
    container_name: celoan-jira
    environment:
      - JVM_MINIMUM_MEMORY=4096m
      - JVM_MAXIMUM_MEMORY=6144m
      - ATL_PROXY_NAME=jira.celoan.opt
      - ATL_PROXY_PORT=80
    ports:
      - "8080:8080"
    retart: always
    volumes:
      - /etc/localtime:/etc/localtime
      - /data/atlassian/jira-data:/var/atlassian/application-data/jira
    extra_hosts:
      - "jira.celoan.opt:10.0.9.33"
      - "wiki.celoan.opt:10.0.9.33"
      - "crowd.celoan.opt:10.0.9.33"
    networks:
      - celoan-atlassian-network
networks: 
  celoan-atlassian-network:
    driver: bridge
    ipam:
      driver: default
      config:
      - subnet: 192.168.107.0/24
[root@server jira]# docker-compose up -d
ERROR: The Compose file './docker-compose.yml' is invalid because:
Unsupported config option for services.jira: 'retart'
[root@server jira]# docker ps
CONTAINER ID   IMAGE                           COMMAND                  CREATED         STATUS         PORTS                                                      NAMES
7d7384708862   nginx                           "/docker-entrypoint.…"   3 minutes ago   Up 3 minutes   0.0.0.0:80->80/tcp, 0.0.0.0:2222->2222/tcp                 nginx-80
7ee762685009   portainer/portainer-ce:latest   "/portainer"             2 years ago     Up 4 days      0.0.0.0:8000->8000/tcp, 0.0.0.0:9443->9443/tcp, 9000/tcp   portainer
9488060c69b7   jira-agent-sso                  "/tini -- /entrypoin…"   4 years ago     Up 3 days      0.0.0.0:8080->8080/tcp                                     celoan-jira
[root@server jira]# 

 

再次修改,并使之生效:

[root@server jira]# cat docker-compose.yml
version: '2'
services:
  jira:
    image: jira-agent-sso
    container_name: celoan-jira
    environment:
      - JVM_MINIMUM_MEMORY=4096m
      - JVM_MAXIMUM_MEMORY=6144m
      - ATL_PROXY_NAME=jira.celoan.opt
      - ATL_PROXY_PORT=80
    ports:
      - "8080:8080"
    restart: always
    volumes:
      - /etc/localtime:/etc/localtime
      - /data/atlassian/jira-data:/var/atlassian/application-data/jira
    extra_hosts:
      - "jira.celoan.opt:10.0.9.33"
      - "wiki.celoan.opt:10.0.9.33"
      - "crowd.celoan.opt:10.0.9.33"
    networks:
      - celoan-atlassian-network
networks: 
  celoan-atlassian-network:
    driver: bridge
    ipam:
      driver: default
      config:
      - subnet: 192.168.107.0/24
[root@server jira]# docker-compose up -d
Recreating celoan-jira ... done
[root@server jira]# docker ps
CONTAINER ID   IMAGE                           COMMAND                  CREATED          STATUS          PORTS                                                      NAMES
270b38034909   jira-agent-sso                  "/tini -- /entrypoin…"   25 seconds ago   Up 24 seconds   0.0.0.0:8080->8080/tcp                                     celoan-jira
7d7384708862   nginx                           "/docker-entrypoint.…"   5 minutes ago    Up 5 minutes    0.0.0.0:80->80/tcp, 0.0.0.0:2222->2222/tcp                 nginx-80
7ee762685009   portainer/portainer-ce:latest   "/portainer"             2 years ago      Up 4 days       0.0.0.0:8000->8000/tcp, 0.0.0.0:9443->9443/tcp, 9000/tcp   portainer
[root@server jira]# 

 

四 补充说明

 

1 常见的重启策略说明

我们可以根据实际需求选择不同的参数:

参数说明
no默认值。容器退出后不重启。
always只要容器退出(无论是因为进程崩溃还是 Docker 服务重启),就总是重启。
unless-stopped类似于 always,但如果容器是被你手动停止的,那么在 Docker 服务重启后,它不会自动启动。
on-failure仅在容器由于非零退出代码(即运行出错)而退出时才重启。

2 如何检查是否设置成功?

你可以通过以下命令查看容器的详细状态,确认 RestartPolicy 部分:

docker inspect <容器ID或容器名> --format='{{.HostConfig.RestartPolicy.Name}}'

温馨提示:

如果你的容器是使用 Docker Compose 管理的,你需要在 yaml 文件中的服务节点下添加 restart: always,然后重新执行 docker-compose up -d 即可生效。

 

 

留言