1202 年了,如果你连 Docker 都不知道是什么,我建议买一本书看看——或者谷歌一下,博客已经写烂了。
为什么有这篇文章,是因为我在真正做容器化改造的时候,发现公司生产环境存在大量的坑:
Ubuntu 应该是全球用户量最多的发行版了,嗯我说的是桌面这一块,折腾过的人都知道,出问题的时候开机会有 “检测到系统错误” 的提示,另外,网上提供的配置或者各种疑难杂症,改了不一定能生效,而且你还不确定改了会不会影响到别的,反正我是不敢用的哈哈(Manjaro 真香)。
CentOS 应该是大家最熟悉的,也是我见过最多应用在生产环境中的。它给我的感觉就是非常稳定,并且网上的资料是一搜索就展现在你面前,而你对着资料改配置,重载就生效,不会搞出什么问题。
公司的生产环境清一色 CentOS 6,但 CentOS 6 已经被官方弃用,不再提供 yum 镜像源,这也意味着很多包你都安装不了,所以你只能升级到 CentOS 7。
问题来了,我能升级吗?
这不得不说到之前线上出现过一个故障:
公司有一台发布构建机器,用来做代码部署,机器上安装了 NodeJS、Go 编译器等,有一天前端的同事说向 SRE 同学提了一个需求:
升级 NodeJS 到 v10 版本,因为以前的 v6 版本太旧了,SRE 同学也没多想,发现 CentOS 6 机器要升级 glibc 才行,于是运维的同事就升级 glibc 之后,升级了 NodeJS;
过了段时间有人部署某服务,该服务使用了 结巴分词 ,部署完发现线上挂了……
嗯,线上环境的 glibc 版本比较低,编译机的 glibc 版本高,部署过去不兼容直接就是启动不了,还好当时回滚的够快
直接用 7 也不是不可以,统一就 OK,但要命的是,发现有些祖传的 PHP 扩展,已经失传了,能兼容但是你怎么保证不出问题对不对?
经历万般挫折,最终使用的是 CentOS 6.9,好在腾讯云有 yum 源,东拼西凑了生产环境的 PHP 扩展之后,开发环境已经完美投入使用。
就是因为这些事情,前前后后花了两三周的时间都在折腾镜像。
CentOS 是真的大!我自己也使用 7 重新打了一个镜像,发现不管怎么清理各种缓存,最终的镜像大小都接近 1G!
虽然说也不是不能用,但我就是有洁癖呀。最后还是选择了 alpine ,把体积减少到 100M 以内。
到这里可能有人问:我们生产环境用的 alpine 也就 60M 左右,没有那么大吧?
之前看过这个项目 Laradock ,它的特点是定制化非常强,基本都是打开一些环境变量就可以构建出你所要的镜像;
但我更倾向于,牺牲一些磁盘空间,制作一个统一的环境。为了方便,线上没必要按照项目复制扩展,维护自己的 Dockerfile,统一都放进去就好了,维护起来也比较方便。
公司目前大量使用 PHP 5.4 和 PHP 7.2,扩展版本比较混乱;
没有直接使用 nginx,而是使用 openresty 1.11.2(主要是传统 IDC 部署缺乏云上 WAF ,需要自行做好限流和 IP 防刷);
我提供的 Dockerfile 是 PHP 5.6 和 PHP 7.2 的最新版本,理论上可以直接升级;而 openresty 使用最新奇数版本,保证生产环境的稳定和安全。
记录一下为什么要花这么长的时间整这个镜像,个人觉得下面列举出来的,都是非常宝贵的经验:
镜像:
apk:
文件权限:
线上排障:
环境标准化:
文件权限:
扩展:
php-fpm.conf:
php.ini:
FROM php:5.6.40-fpm-alpine3.8
LABEL maintainer="??? ??@???.com>"
ENV TZ=Asia/Shanghai
RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories && \
# deps
apk --no-cache add bind-tools \
git \
make \
openssh-client \
php5-mcrypt \
php5-sysvmsg \
php5-sysvsem \
php5-sysvshm \
tzdata \
freetype-dev \
gettext-dev \
imagemagick-dev \
libmemcached-dev \
libpng-dev \
libzip-dev \
jpeg-dev \
rabbitmq-c-dev \
&& \
cp /usr/lib/php5/modules/mcrypt.so /usr/local/lib/php/extensions/no-debug-non-zts-20131226/ && \
cp /usr/lib/php5/modules/sysvmsg.so /usr/local/lib/php/extensions/no-debug-non-zts-20131226/ && \
cp /usr/lib/php5/modules/sysvsem.so /usr/local/lib/php/extensions/no-debug-non-zts-20131226/ && \
cp /usr/lib/php5/modules/sysvshm.so /usr/local/lib/php/extensions/no-debug-non-zts-20131226/ && \
# DNS
[ ! -e /etc/nsswitch.conf ] && echo 'hosts: files dns' > /etc/nsswitch.conf && \
# timezone
ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && \
echo '$TZ' > /etc/timezone && \
# /www
# /wwwlog
# /app
addgroup -g 500 -S www && \
adduser -u 500 -D -S -G www www && \
mkdir /www && mkdir /wwwlog && mkdir -p /app && \
chown -R www:www /www && chown -R www:www /wwwlog && chown -R www:www /app && \
addgroup www tty && \
sed -i 's/\/home\/www:\/bin\/false/\/home\/www:\/bin\/ash/g' /etc/passwd && \
deluser --remove-home www-data && \
# password
passwd root -d "!!!Production!!!" && \
passwd www -d "!!!Production!!!" && \
# ssh-key
mkdir -p /root/.ssh && \
echo ???==|base64 -d>/root/.gitconfig && \
echo ???==|base64 -d>/root/.ssh/config && \
echo ???==|base64 -d>/root/.ssh/id_rsa && \
echo ???==|base64 -d>/root/.ssh/id_rsa.pub && \
echo ???==|base64 -d>/root/.ssh/known_hosts && \
chmod 600 /root/.ssh/id_rsa && \
# composer
wget -O /usr/local/bin/composer https://mirrors.cloud.tencent.com/composer/composer.phar && \
chmod +x /usr/local/bin/composer && \
/usr/local/bin/composer config -g repos.packagist composer https://mirrors.cloud.tencent.com/composer/ && \
# ext
docker-php-ext-configure zip --with-libzip && \
docker-php-ext-configure gd --with-jpeg-dir=/usr/lib --with-freetype-dir=/usr/include/freetype2 && \
pecl install -o -f amqp-1.10.2 && \
pecl install -o -f memcached-2.2.0 && \
pecl install -o -f imagick-3.4.4 && \
pecl install -o -f rar-4.2.0 && \
pecl install -o -f redis-4.3.0 && \
pecl download yaf-2.3.5 && tar zxvf yaf-2.3.5.tgz && cd yaf-2.3.5 && phpize && ./configure && \
make && make install && cd .. && rm -rf yaf-2.3.5 && \
docker-php-ext-install bcmath gettext mysqli pcntl sockets pdo_mysql mysqli mbstring gd zip opcache && \
docker-php-ext-enable amqp mcrypt memcached imagick rar redis sysvmsg sysvsem sysvshm yaf && \
rm -rf /tmp/pear /var/cache/apk/* /tmp/* && \
# php-fpm.conf
echo "[global]" > /usr/local/etc/php-fpm.d/zz-docker.conf && \
echo "daemonize = no" >> /usr/local/etc/php-fpm.d/zz-docker.conf && \
# www.conf
rm -f /usr/local/etc/php-fpm.d/www.conf.default && \
sed -i "s/www-data/www/g" /usr/local/etc/php-fpm.d/www.conf && \
sed -i "s/pm.max_children = 5/pm.max_children = 128/g" /usr/local/etc/php-fpm.d/www.conf && \
sed -i "s/listen = 127.0.0.1:9000/listen = 127.0.0.1:9056/g" /usr/local/etc/php-fpm.d/www.conf && \
sed -i "s/;pm.max_requests = 500/pm.max_requests = 1024/g" /usr/local/etc/php-fpm.d/www.conf && \
sed -i "s/;request_slowlog_timeout = 0/request_slowlog_timeout = 5/g" /usr/local/etc/php-fpm.d/www.conf && \
sed -i "s/;request_terminate_timeout = 0/request_terminate_timeout = 30/g" /usr/local/etc/php-fpm.d/www.conf && \
sed -i 's/;slowlog = log\/\$pool.log.slow/slowlog = \/proc\/self\/fd\/2/g' /usr/local/etc/php-fpm.d/www.conf && \
sed -i "s/;access.format/access.format/g" /usr/local/etc/php-fpm.d/www.conf && \
# php.ini
cp /usr/local/etc/php/php.ini-production /usr/local/etc/php/php.ini && \
sed -i "s/;opcache.enable_cli=0/opcache.enable_cli=1/g" /usr/local/etc/php/php.ini && \
sed -i "s/expose_php = On/expose_php = Off/g" /usr/local/etc/php/php.ini
WORKDIR /app
FROM php:7.2.34-fpm-alpine3.12
LABEL maintainer="??? ??@???.com>"
ENV TZ=Asia/Shanghai
RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories && \
# deps
apk update && \
apk --no-cache add bind-tools \
git \
make \
openssh-client \
tzdata \
freetype-dev \
libmemcached-dev \
libpng-dev \
jpeg-dev \
&& \
# DNS
[ ! -e /etc/nsswitch.conf ] && echo 'hosts: files dns' > /etc/nsswitch.conf && \
# timezone
ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && \
echo '$TZ' > /etc/timezone && \
# /www
# /wwwlog
# /app
addgroup -g 500 -S www && \
adduser -u 500 -D -S -G www www && \
mkdir /www && mkdir /wwwlog && mkdir -p /app && \
chown -R www:www /www && chown -R www:www /wwwlog && chown -R www:www /app && \
addgroup www tty && \
sed -i 's/\/home\/www:\/sbin\/nologin/\/home\/www:\/bin\/ash/g' /etc/passwd && \
deluser --remove-home www-data && \
# password
passwd -u root -d "!!!Production!!!" && \
passwd -u www -d "!!!Production!!!" && \
# ssh-key
mkdir -p /root/.ssh && \
echo ???==|base64 -d>/root/.gitconfig && \
echo ???==|base64 -d>/root/.ssh/config && \
echo ???==|base64 -d>/root/.ssh/id_rsa && \
echo ???==|base64 -d>/root/.ssh/id_rsa.pub && \
echo ???==|base64 -d>/root/.ssh/known_hosts && \
chmod 600 /root/.ssh/id_rsa && \
# composer
wget -O /usr/local/bin/composer https://mirrors.cloud.tencent.com/composer/composer.phar && \
chmod +x /usr/local/bin/composer && \
/usr/local/bin/composer config -g repos.packagist composer https://mirrors.cloud.tencent.com/composer/ && \
# ext
docker-php-ext-configure gd --with-jpeg-dir=/usr/lib --with-freetype-dir=/usr/include/freetype2 && \
pecl install -o -f memcached-3.1.5 && \
pecl install -o -f redis-5.3.4 && \
docker-php-ext-install bcmath pdo_mysql gd opcache && \
docker-php-ext-enable memcached redis && \
rm -rf /tmp/pear /var/cache/apk/* /tmp/* && \
# php-fpm.conf
echo "[global]" > /usr/local/etc/php-fpm.d/zz-docker.conf && \
echo "daemonize = no" >> /usr/local/etc/php-fpm.d/zz-docker.conf && \
# www.conf
rm -f /usr/local/etc/php-fpm.d/www.conf.default && \
sed -i "s/www-data/www/g" /usr/local/etc/php-fpm.d/www.conf && \
sed -i "s/pm.max_children = 5/pm.max_children = 256/g" /usr/local/etc/php-fpm.d/www.conf && \
sed -i "s/listen = 127.0.0.1:9000/listen = 127.0.0.1:9072/g" /usr/local/etc/php-fpm.d/www.conf && \
sed -i "s/;pm.max_requests = 500/pm.max_requests = 1000/g" /usr/local/etc/php-fpm.d/www.conf && \
sed -i "s/;request_slowlog_timeout = 0/request_slowlog_timeout = 5/g" /usr/local/etc/php-fpm.d/www.conf && \
sed -i "s/;request_terminate_timeout = 0/request_terminate_timeout = 30/g" /usr/local/etc/php-fpm.d/www.conf && \
sed -i 's/;slowlog = log\/\$pool.log.slow/slowlog = \/proc\/self\/fd\/2/g' /usr/local/etc/php-fpm.d/www.conf && \
# php.ini
cp /usr/local/etc/php/php.ini-production /usr/local/etc/php/php.ini && \
sed -i "s/;opcache.enable_cli=0/opcache.enable_cli=1/g" /usr/local/etc/php/php.ini && \
sed -i "s/expose_php = On/expose_php = Off/g" /usr/local/etc/php/php.ini
WORKDIR /app
FROM openresty/openresty:1.19.3.2-alpine-apk
LABEL maintainer="??? ??@???.com>"
ENV TZ=Asia/Shanghai
RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories && \
# deps
apk update && \
apk --no-cache add bind-tools \
tzdata \
&& \
# DNS
[ ! -e /etc/nsswitch.conf ] && echo 'hosts: files dns' > /etc/nsswitch.conf && \
# timezone
ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && \
echo '$TZ' > /etc/timezone && \
# /www
# /wwwlog
# /app
addgroup -g 500 -S www && \
adduser -u 500 -D -S -G www www && \
mkdir /www && mkdir /wwwlog && mkdir -p /app && \
chown -R www:www /www && chown -R www:www /wwwlog && chown -R www:www /app && \
addgroup www tty && \
sed -i 's/\/home\/www:\/sbin\/nologin/\/home\/www:\/bin\/ash/g' /etc/passwd && \
# password
passwd -u root -d "!!!Production!!!" && \
passwd -u www -d "!!!Production!!!"
COPY conf/nginx.conf /usr/local/openresty/nginx/conf/nginx.conf
pcre_jit on;
user www www;
worker_processes 1;
error_log /usr/local/openresty/nginx/logs/error.log error;
worker_rlimit_nofile 65535;
events {
use epoll;
worker_connections 65535;
}
http {
include mime.types;
default_type application/octet-stream;
server_tokens off;
sendfile on;
tcp_nopush on;
tcp_nodelay on;
server_names_hash_bucket_size 512;
client_max_body_size 8m;
client_header_buffer_size 32k;
large_client_header_buffers 4 32k;
proxy_buffers 32 128k;
proxy_buffer_size 128k;
proxy_busy_buffers_size 128k;
client_body_timeout 10;
client_header_timeout 10;
send_timeout 30;
keepalive_timeout 60;
log_format main escape=json '{"@timestamp":"$time_iso8601",'
'"scheme":"$scheme",'
'"remote_host":"$host",'
'"clientip":"$remote_addr",'
'"bytes":$body_bytes_sent,'
'"cost":$request_time,'
'"referer":"$http_referer",'
'"agent":"$http_user_agent",'
'"time_local":"$time_local",'
'"xforward":"$http_x_forwarded_for",'
'"method":"$request_method",'
'"request":"$request_uri",'
'"uri":"$uri",'
'"postData":"$request_body",'
'"cookieData":"$http_cookie",'
'"httpversion":"$server_protocol",'
'"reqid":"$reqid",'
'"remote_port":"$remote_port",'
'"server_port":"$server_port",'
'"status":$status}';
fastcgi_connect_timeout 300;
fastcgi_send_timeout 300;
fastcgi_read_timeout 300;
fastcgi_buffer_size 64k;
fastcgi_buffers 4 64k;
fastcgi_busy_buffers_size 128k;
fastcgi_temp_file_write_size 256k;
fastcgi_intercept_errors on;
gzip on;
gzip_vary on;
gzip_comp_level 5;
gzip_buffers 16 8k;
gzip_min_length 1k;
gzip_proxied any;
gzip_http_version 1.0;
gzip_disable "msie6";
gzip_proxied expired no-cache no-store private auth;
gzip_types text/plain application/javascript application/x-javascript text/javascript text/css application/xml application/xml+rss application/json;
server {
listen 80 default_server;
server_name _;
return 444;
access_log /usr/local/openresty/nginx/logs/access.log main;
include add_header_reqid.conf;
}
include /usr/local/openresty/nginx/conf/vhost/*.conf;
}
嗯,真实的生产环境配置十分混乱,我做了格式化,大家拿去用吧
文章来源于本人博客,发布于 2021-06-13,原文链接:https://imlht.com/archives/236/