通常我們乙個完整的應用映象有兩部分組成,乙個是執行時環境,乙個是應用程式。我們以php應用為例,乙個完整的php應用需要包含openresty + php兩個服務來配置執行時環境,然後再加上php**,來完成一整個php應用的發布。php**產生的日誌由程式自行控制,一般都會按天滾動,在日誌量較大的情況下,也可能按小時滾動,或者按照單個日誌檔案的大小來實現滾動。而nginx和php服務的日誌預設情況下並不支援這種滾動,所以預設情況下,乙個openresty+php容器在其生命週期內,就只會寫乙個日誌檔案,如果該容器長時間執行,openresty與php服務的訪問日誌就會變的非常巨大,給我們日誌清理造成了不便。
雖然預設情況下,openresty和php等服務的訪問日誌並不會自動滾動,但我們卻可以使用一些第三方工具來實現。在傳統的應用部署中,我們使用logrotate + crontab來實現openresty 與php等服務的日誌滾動。而事實上,這一方案在容器環境下仍然適用。我們的解決方案是,在每個服務的基礎映象中配置好logrotate和crontab,這樣在容器執行起來後,就會自動根據配置好的輪轉策略實現日誌滾動。
我們仍然以openresty+php為例,給出乙個openresty+php的基礎映象的dockerfile示例如下:
maintainer yanwei "[email protected]"
env nginx_home /usr/local/ngx_openresty
env php_home /usr/local/php7
run groupadd -g 571 www && \
useradd -u 571 -g 571 www && \
yum install -y iproute cronie logrotate
add lib64.tar.gz /
add openresty.tar.gz /
add phpfpm7.tar.gz /
add php.ini $php_home/etc/php.ini
add phpfpm.conf $php_home/etc/phpfpm.conf
add nginx.conf $nginx_home/nginx/conf/nginx.conf
add libnsssysinit.so /usr/lib64/libnsssysinit.so
add build.sh /
add run.sh /
add crontab /etc/crontab
add logrotate /etc/cron.daily/logrotate
add logrotate.conf /etc/logrotate.conf
run chown www -r /home/www $nginx_home $php_home && \
chmod +x /build.sh /run.sh /etc/cron.daily/logrotate /usr/lib64/libnsssysinit.so
expose 80
entrypoint ["/build.sh"]
cmd ["/run.sh"]
在上面的dockerfile中,我們通提取.so
檔案並打入到映象中的方式來完成了openresty和php的安裝。其中lib64.tar.gz即openresty和php7所依賴的全部.so
檔案,opernsty.tar.gz和phpfpm7.tar.gz為編譯安裝後的openresty和php7的**檔案。我們需要注意的大概有如下幾個檔案:
build.sh
run.sh
crontab
logrotate
logrotate.conf
#!/bin/bash
php_home=/usr/local/php7
/usr/sbin/crond
$php_home/sbin/php-fpm -c $php_home/etc/php.ini -y $php_home/etc/phpfpm.conf
/usr/local/ngx_openresty/nginx/sbin/nginx -c /usr/local/ngx_openresty/nginx/conf/nginx.conf -g "daemon off;"
這個檔案中,啟動了三個服務,分別為crond,php-fpm以及openresty。這很好理解,我們需要openresty和php環境以提供基本的php應用的web功能,需要crontab來實現服務的日誌輪轉。
logrotate.conf提供logrotate的輪轉配置檔案,存放到映象的/etc目錄下,內容如下:
在該配置檔案中,定義了對如下三個日誌檔案做輪**
可以看到,這三個日誌檔案在這裡並非真正意義上的日誌檔案路徑,而是使用了三個佔位符,由於在我們的映象中,日誌檔案的路徑並不固定,只有在容器啟動的那一刻才能確定具體的日誌路徑。所以我這裡採用了docker-entrypoint的方式,在啟動的時候,執行build.sh指令碼來實現日誌路徑的替換。build.sh中關於日誌部分的定義如下:
##############################
# log configration #
##############################
php_home=/usr/local/php7
phpconfigfile=$php_home/etc/php.ini
phpfpmconfigfile=$php_home/etc/phpfpm.conf
nginxconfigfile=/usr/local/ngx_openresty/nginx/conf/nginx.conf
logrotatefile=/etc/logrotate.conf
logdir=/home/www/logs
srvlogdir=$/srvlogs
if [ ! -z $ ];then
host_name=$
else
host_name=$(hostname)
fielse
exit 1
finginxlogdir=$/nginx
phplogdir=$/php
if [ $x == "did_format"x ];then
sed -i "s//did_format/g" $nginxconfigfile
else
sed -i "s//real_ip/g" $nginxconfigfile
finginxaccesslog=$/nginx.access.log
nginxerrorlog=$/nginx.error.log
phpfpmerrorlog=$/phpfpm.error.log
phpfpmaccesslog=$/phpfpm.access.log
phpfpmslowlog=$/phpfpm.slow.log
phperrorlog=$/php.error.log
sed -i "s@@$@g" $nginxconfigfile
sed -i "s@@$@g" $nginxconfigfile
sed -i "s@@$@g" $phpfpmconfigfile
sed -i "s@@$@g" $phpfpmconfigfile
sed -i "s@@$@g" $phpfpmconfigfile
sed -i "s@@$@g" $phpconfigfile
sed -i "s@@$@g" $logrotatefile
sed -i "s@@$@g" $logrotatefile
sed -i "s@@$@g" $logrotatefile
exec "$@"
#!/bin/sh
/usr/sbin/logrotate -s /var/lib/logrotate/logrotate.status -f /etc/logrotate.conf
exitvalue=$?
if [ $exitvalue != 0 ]; then
/usr/bin/logger -t logrotate "alert exited abnormally with [$exitvalue]"
fiexit 0
這個指令碼比較簡單,就是通過logrotate執行輪轉。其中-f
表示強制輪轉,-s
用於記錄每一次輪轉的狀態。
最後定義具體crontab的執行時間,檔案為/etc/crontab,內容如下:
shell=/bin/bash
path=/sbin:/bin:/usr/sbin:/usr/bin
mailto=root
# for details see man 4 crontabs
# example of job definition:
# .---------------- minute (0 - 59)
# | .------------- hour (0 - 23)
# | | .---------- day of month (1 - 31)
# | | | .------- month (1 - 12) or jan,feb,mar,apr ...
# | | | | .---- day of week (0 - 6) (sunday=0 or 7) or sun,mon,tue,wed,thu,fri,sat
# | | | | |
# * * * * * user-name command to be executed
0 0 * * * root /usr/bin/run-parts /etc/cron.daily
至此,實現了容器內服務日誌的自動輪轉。 java實現日誌服務
我們在伺服器程式中經常用到日誌,日誌對於我們排查問題有很大的幫助。下面是日誌服務的思路以及實現 思路 多個生產者單個消費者的設計方式,每個呼叫log的操作都相當於乙個生產者,而後台的日誌執行緒則相當於消費者。public class loggerservice public void start p...
docker 中執行 redis 服務
先使用 dockerfile 建立乙個 redis 容器 from ubuntu latest run apt get update run apt get y install redis server expose 6379 entrypoint usr bin redis server 使用do...
Docker中開啟sshd服務
ssh服務安裝 開機自起 在 root目錄下建立run.sh指令碼,新增如下內容 bin bash service sshd restart while do sleep 10 done其實開機自起可以用cmd的,但是暫時不會。就統一用指令碼執行的方式防止退出,感覺可調控行蠻好的。儲存修改 開啟服務...