如果在本機安裝 apache2 或 nginx 時想要 reload config 的話我們通常會使用下列的指令:
# nginx
nginx -s reload
# apache2
service httpd reload
但在 docker 的環境下就沒有那麼簡單,像 apache 的 reload 是把 script 寫在 service 的 config 裡面,不一定每個 image 裡面都有包含這個指令,CentOS 的我記得好像就沒有,為了要兼容所有的環境,我們可以利用 kill -USR1
這個方式套用到每個我們想要 reload without restart 的專案上面。
apache2
首先在根目錄建立兩個網頁檔:
- ./www/1/index.html
- ./www/2/index.html
各別會在網頁印出 1 以及 2 的內容識別。
docker-compose.yml
version: "3.9"
services:
http:
ports:
- "80:80"
container_name: httpd
image: httpd
restart: always
volumes:
- "./www:/www"
- "./config/httpd:/usr/local/apache2/conf:ro"
我們建立了一個名為 http 的 container,使用 httpd 的 image,並且把 www
目錄掛進去,我事先把 httpd 的 config 複製出來以便在外面修改內容,接下來跑 docker compose up -d
,打上 IP 後可以看到 httpd 傳統的首頁內容 It works!。
接著我們修改 httpd.conf:
DocumentRoot "/usr/local/apache2/htdocs"
<Directory "/usr/local/apache2/htdocs">
# 改為
DocumentRoot "/www/1"
<Directory "/www/1">
我們先使用 docker compose restart
測試,執行後 refresh 網頁可以看到我們要的 1,接著再把 config 改成:
DocumentRoot "/www/2"
<Directory "/www/2">
這次我們使用 docker compose kill -s USR1 http
,此時我們可以看到 container 活得好好的,但 refresh 頁面後得到我們想要的 2 了,他的原理就是呼叫 container 內的 httpd daemon 去重新整理他的 service。
nginx
docker-compose.yml
version: "3.9"
services:
http:
ports:
- "80:80"
container_name: nginx
image: nginx
restart: always
volumes:
- "./www:/www"
- "./config/nginx/conf.d/default.conf:/etc/nginx/conf.d/default.conf:ro"
一樣,我們事前複製了 nginx 的 config 出來重新掛載回去,啟動 container 以後看見 nginx 的預設字樣 Welcome to nginx!。
接著我們修改 defalut.conf
root /usr/share/nginx/html;
# 改為
root /www/1;
跟 apache2 一樣我們先使用 docker compose restart
,可以順利看到 1 的結果,接著我們將 config 修改為:
root /www/2;
使用 docker compose exec http nginx -s reload
,我們就可以順利看到 2 了,nginx 跟 apache2 的 container 啟動方式不太一樣,所以不能用 kill
的方法,但事實上在 nginx 的 logrotate config 裡面他使用的方式也是:
kill -USR1 `cat /var/run/nginx.pid`
上面介紹了兩個主流網頁伺服器的重取 config 的目的是在當我們把 server 的 log 掛到我們本機目錄時,我們可能會需要依照情況在本機執行 logrotate
的動作,這樣就可以把 reload 腳本寫在本機的 logrotate config 的 postrotate/endscript
裡面了。
這邊附上 logrotate for docker 基本的配置:
nginx-docker
/YOUR_PATH_TO_LOG/*.log {
daily
missingok
rotate 52
compress
delaycompress
notifempty
create 640 nginx adm
sharedscripts
postrotate
sudo docker exec YOUR_CONTAINER_NAME nginx -s reload
endscript
}
httpd-docker
/YOUR_PATH_TO_LOG/*.log {
daily
missingok
rotate 14
compress
delaycompress
notifempty
sharedscripts
postrotate
sudo docker kill -s USR1 YOUR_CONTAINER_NAME
endscript
}