強制異常容器重啟,讓你的Docker錦上添花
今天我們接著上次的docker健康檢查機(jī)制那篇文章,講述一下如何給不健康的容器進(jìn)行重啟。另外有讀者反饋有幾個參數(shù)不是很理解,我們會在這篇文章里再補充講解一下。
Docker在1.12版本之后提供了HEALTHCHECK指令,可以設(shè)定一行command用來判斷服務(wù)的狀態(tài)是否正常,這樣可以更準(zhǔn)確地判斷服務(wù)狀態(tài)。
HEALTHCHECK Container啟動后的初始狀態(tài)為starting,在指令檢查成功后,狀態(tài)會更改為healthy,如果連續(xù)失敗超過指定次數(shù)則會改為unhealthy??聪翲ealthCheck的工作機(jī)制。
HEALTHCHECK參數(shù)選項:
--interval: Health check時間間隔,預(yù)設(shè)為30秒
--timeout:當(dāng)Health check超過此設(shè)定的時間,則會視為失敗,預(yù)設(shè)為30秒
--retries:當(dāng)Health check連續(xù)失敗次數(shù)超過此設(shè)定時,則會將狀態(tài)更改為,預(yù)設(shè)為3次unhealthy
--start-period:啟動時間,預(yù)設(shè)為0秒
HEALTHCHECK可以通過Dockerfile或是docker-compose.yml設(shè)定:
Dockerfile 示例
在Dockerfile中,HEALTHCHECK指令格式為
HEALTHCHECK [options] CMD <command>
<command>可以是shell指令或是exec格式(和其他Dockerfile指令相同,可以參考ENTRYPOINT)。而一個Dockerfile中只能有一個HEALTHCHECK指令,如果同時有多個HEALTHCHECK指令,則只有最后一個有效。
<command>的返回值代表container的狀態(tài):
0:成功,container is healthy
1:失敗,如果失敗超過指定次數(shù),則container為unhealthy
2: reserved,不要使用這個值
假設(shè)我們的container服務(wù)是web服務(wù),我們可以使用來檢查服務(wù)是否正常運行,例如:每30秒檢查一次是否可在5秒內(nèi)響應(yīng)請求:curl http://localhost:3000
# ...
HEALTHCHECK --interval=30s --timeout=5s --retries=5 --start_period=30s \
CMD curl -fs http://localhost:3000/ || exit 1
# ...
Docker-compose 示例
docker-compose.yml的healthcheck,示例如下:
version: "3.7"
services:
api:
restart: always
image: api
container_name: api
ports:
- 3000:3000
build:
context: ./api
healthcheck:
test: curl -fs http://localhost:3000/ || exit 1
interval: 30s
timeout: 5s
retries: 5
start_period: 30s
networks:
- net
networks:
net:
name: net
driver: bridge
其中test必須是string或list.如果是list,第一個item必須是NONE,或CMD-SHELL。如果是string,則等同于CMD-SHELL。
確認(rèn)健康狀態(tài)
在設(shè)定好health check指令之后,接著啟動container,檢查container狀態(tài)時可以看到初始狀態(tài)是:health: starting
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
6c7b9ca321d2 api:1.0.0 "uwsgi --ini /home/d…" 5 seconds ago Up 2 seconds (health: starting) 0.0.0.0:3000->3000/tcp api
過30秒之后再執(zhí)行一次docker ps,可以看到container的狀態(tài)變成:healthy
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
6c7b9ca321d2 api:1.0.0 "uwsgi --ini /home/d…" 35 seconds ago Up 32 seconds (healthy) 0.0.0.0:3000->3000/tcp api
而如果連續(xù)失敗超過指定次數(shù),狀態(tài)會變成unhealthy。
關(guān)鍵步驟:重新啟動不正常的容器
以上的步驟只有檢查container的健康狀態(tài),但沒有針對unhealthy container做任何處理,這部分我們可以搭配docker-autoheal來重啟unhealthy container。先看下AutoHeal的工作機(jī)制。
autoheal可以直接使用docker執(zhí)行,或是寫在docker-compose中:
使用 docker 指令:
$ docker run -d \
--name autoheal \
--restart=always \
-e AUTOHEAL_CONTAINER_LABEL=all \
-v /var/run/docker.sock:/var/run/docker.sock \
willfarrell/autoheal
使用docker-compose指令:
version: "3.7"
services:
autoheal:
restart: always
image: willfarrell/autoheal
container_name: autoheal
environment:
- AUTOHEAL_CONTAINER_LABEL=all
volumes:
- /var/run/docker.sock:/var/run/docker.sock
然后執(zhí)行 docker-compose up -d autoheal 就可以啟動。
啟動之后可以通過docker ps觀察unhealthy的容器是否重啟了。也可以查看autoheal的日志查看是否有啟動記錄。
最后再給大家介紹一種模擬unhealthy的方法,正常情況下都是healthy的,可以通過修改命令來模擬unhealthy。比如模擬mysql的服務(wù),我們可以使用如下命令。
test: ["CMD", "nc -vz localhost 3307 || exit 1"]
正常監(jiān)聽3306端口,我們用3307連接檢查,就會一直處于unhealthy狀態(tài),這個時候我們可以通過autoheal的日志觀察到對mysql容器的重啟。
有了這個機(jī)制,以后docker假死的情況就可以自動重啟了。這個檢查和自動重啟機(jī)制對于數(shù)據(jù)庫或者tomcat服務(wù)都非常有用。如果使用過程中有什么問題也歡迎發(fā)消息給我們。