实践说明:基于RHEL7(CentOS7.9)部署docker环境(23.0.1、24.0.2),编排也可应用于RHEL7-9(如AlmaLinux9.1),但因为docker的特性,适用场景是不限于此的。
文档形成时期:2017-2023年
因系统或软件版本不同,构建部署可能略有差异,但本文未做细分,对稍有经验者应不存在明显障碍。
因软件世界之复杂和个人能力之限,难免疏漏和错误,欢迎指正。
文章目录
创建数据持久化目录
mkdir -p /opt/docker/{nginx_cfg,nginx_log,php_cfg,php_log,redis_cfg,redis_log} /opt/web
Docker单独构建PHP镜像
compose构建过程中,PHP是最复杂最紧要的,先单独构建PHP镜像很有必要。
拉取官方7.4的php-fpm(默认是拉取最新版)
docker pull php:7.4.33-fpm
或通过Dockerfile构建一个新的镜像(推荐)
docker buildx build -t tmtcha/php:7.4.33-fpm-tmp -f /root/sh/Dockerfiles/Independent/php_Dockerfile_tmp .
#创建自定义网络,并指定网段、网关,只有定义了网段,才可以使用此网络为容器分配固定IP
docker network create -d bridge --subnet 10.1.4.0/24 --gateway 10.1.4.1 custom_bridge_net
运行容器
docker run -d --name phpfpm74-tmp -v /opt/web/:/opt/web --network custom_bridge_net --ip 10.1.4.3 tmtcha/php:7.4.33-fpm-tmp
查看默认配置、版本和已安装模块
docker官方php7.4.33-fpm的镜像使用的系统版本是基于Debian11
docker exec phpfpm74 /bin/bash -c 'cat /etc/issue'
Debian GNU/Linux 11 \n \l
查看默认源
docker exec phpfpm74-tmp /bin/bash -c 'cat /etc/apt/sources.list'
# deb http://snapshot.debian.org/archive/debian/20221114T000000Z bullseye main
deb http://deb.debian.org/debian bullseye main
# deb http://snapshot.debian.org/archive/debian-security/20221114T000000Z bullseye-security main
deb http://deb.debian.org/debian-security bullseye-security main
# deb http://snapshot.debian.org/archive/debian/20221114T000000Z bullseye-updates main
deb http://deb.debian.org/debian bullseye-updates main
查看php版本
[root@localhost ~]# docker exec phpfpm74 /bin/bash -c 'php -version'
PHP 7.4.33 (cli) (built: Nov 15 2022 06:05:55) ( NTS )
Copyright (c) The PHP Group
Zend Engine v3.4.0, Copyright (c) Zend Technologies
官方php7.4.33默认安装模块
[root@localhost ~]# docker exec phpfpm74 /bin/bash -c 'php -m'
[PHP Modules]
Core
ctype
curl
date
dom
fileinfo
filter
ftp
hash
iconv
json
libxml
mbstring
mysqlnd
openssl
pcre
PDO
pdo_sqlite
Phar
posix
readline
Reflection
session
SimpleXML
sodium
SPL
sqlite3
standard
tokenizer
xml
xmlreader
xmlwriter
zlib
[Zend Modules]
- 和php7.1.33的差不多,仅多一个sodium
配置拷贝出来:
mkdir /root/recycle_bin/phpfpm74;docker cp phpfpm74:/usr/local/etc /root/recycle_bin/phpfpm74
php_Dockerfile
cat /root/sh/Dockerfiles/Independent/php_Dockerfile
FROM php:7.4.33-fpm
MAINTAINER Fisher "N"
# 设置时区
ENV TZ=Asia/Shanghai
#Download PHP extensions
#ADD https://raw.githubusercontent.com/mlocati/docker-php-extension-installer/master/install-php-extensions /usr/local/bin/
#RUN chmod uga+x /usr/local/bin/install-php-extensions && sync
COPY --from=mlocati/php-extension-installer /usr/bin/install-php-extensions /usr/bin/
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone \
&& mv /etc/apt/sources.list /etc/apt/sources.list.bak \
&& echo 'deb https://mirrors.aliyun.com/debian/ bullseye main non-free contrib ' > /etc/apt/sources.list \
&& echo 'deb-src https://mirrors.aliyun.com/debian/ bullseye main non-free contrib ' >> /etc/apt/sources.list \
&& echo 'deb https://mirrors.aliyun.com/debian-security/ bullseye-security main ' >> /etc/apt/sources.list \
&& echo 'deb-src https://mirrors.aliyun.com/debian-security/ bullseye-security main ' >> /etc/apt/sources.list \
&& echo 'deb https://mirrors.aliyun.com/debian/ bullseye-updates main non-free contrib ' >> /etc/apt/sources.list \
&& echo 'deb-src https://mirrors.aliyun.com/debian/ bullseye-updates main non-free contrib ' >> /etc/apt/sources.list \
&& echo 'deb https://mirrors.aliyun.com/debian/ bullseye-backports main non-free contrib ' >> /etc/apt/sources.list \
&& echo 'deb-src https://mirrors.aliyun.com/debian/ bullseye-backports main non-free contrib ' >> /etc/apt/sources.list \
&& mkdir /opt/web && mkdir -p /usr/local/var/log && touch /usr/local/var/log/php-fpm.log && touch /usr/local/var/log/php_errors.log \
&& chown www-data:www-data /usr/local/var/log/php-fpm.log /usr/local/var/log/php_errors.log \
&& DEBIAN_FRONTEND=noninteractive apt-get update -q \
&& DEBIAN_FRONTEND=noninteractive apt-get install -qq -y \
curl \
git \
zip unzip \
&& install-php-extensions \
bcmath \
bz2 \
calendar \
exif \
gd \
intl \
ldap \
memcached \
mysqli \
opcache \
pdo_mysql \
pdo_pgsql \
pgsql \
redis \
soap \
xsl \
zip \
sockets \
swoole \
yaf \
memcached \
mongodb-stable \
mcrypt \
iconv \
mbstring \
gettext \
gmp \
ftp \
pcntl \
shmop \
sysvsem \
sysvshm \
sqlsrv pdo_sqlsrv \
odbc \
xmlrpc \
geoip \
@composer-2.5.8
可停止并清理之前创建的测试用的临时镜像和临时容器:
docker stop phpfpm74-tmp
docker rm phpfpm74-tmp
docker rmi tmtcha/php:7.4.33-fpm-tmp
重新构建
docker buildx build -t tmtcha/php:7.4.33-fpm-v1.01 -f /root/sh/Dockerfiles/Independent/php_Dockerfile .
构建后的大小是519MB。
创建容器
docker run -d --name phpfpm74-v1.01 -v /opt/web/:/opt/web --network custom_bridge_net --ip 10.1.4.3 tmtcha/php:7.4.33-fpm-v1.01
后面要通过Compose整体构建,所以这里创建的容器仅做测试分析,不必留存,可以清理了。docker stop phpfpm74-tmp; docker rm phpfpm74-v1.01
后面要通过Compose整体构建,所以创建的网络仅做测试分析,不必留存,可以清理了。docker network rm custom_bridge_net
php.ini配置
cd /opt/docker/php_cfg/php
cp -ap php.ini-production php.ini
测试配置
docker exec phpfpm74-v1.01 /bin/bash -c "php-fpm -t"
重载配置
docker exec phpfpm74-v1.01 /bin/bash -c "kill -USR2 `docker exec phpfpm74-v1.01 /bin/bash -c 'ps aux | grep "php-fpm: master process" | grep -v "grep" | sed "s/\s\s*/ /g" | cut -d" " -f 2'`"
修改必要配置
error_log = php_errors.log
设置扩展
追加:
extension_dir = "/usr/local/lib/php/extensions/no-debug-non-zts-20190902"
extension=bcmath.so
extension=exif.so
extension=gmp.so
extension=mcrypt.so
extension=mysqli.so
extension=pcntl.so
extension=pdo_sqlsrv.so
extension=shmop.so
;extension=sodium.so
extension=sysvsem.so
extension=xsl.so
extension=bz2.so
extension=gd.so
extension=intl.so
extension=memcached.so
extension=odbc.so
extension=pdo_mysql.so
extension=pgsql.so
extension=soap.so
extension=sqlsrv.so
extension=sysvshm.so
extension=yaf.so
extension=calendar.so
extension=gettext.so
extension=ldap.so
extension=mongodb.so
extension=pdo_pgsql.so
extension=redis.so
extension=sockets.so
extension=swoole.so
extension=xmlrpc.so
extension=zip.so
zend_extension=opcache.so
[opcache]
;开启opcache
opcache.enable=1
;CLI环境下,PHP启用OPcache
opcache.enable_cli=1
;OPcache共享内存存储大小,单位MB
opcache.memory_consumption=128
;PHP使用了一种叫做字符串驻留(string interning)的技术来改善性能。例如,如果你在代码中使用了1000次字符串“foobar”,在PHP内部只会在第一使用这个字符串的时候分配一个不可变的内存区域来存储这个字符串,其他的999次使用都会直接指向这个内存区域。这个选项则会把这个特性提升一个层次——默认情况下这个不可变的内存区域只会存在于单个php-fpm的进程中,如果设置了这个选项,那么它将会在所有的php-fpm进程中共享。在比较大的应用中,这可以非常有效地节约内存,提高应用的性能。这个选项的值是以兆字节(megabytes)作为单位,如果把它设置为16,则表示16MB,默认是4MB
opcache.interned_strings_buffer=8
;这个选项用于控制内存中最多可以缓存多少个PHP文件。这个选项必须得设置得足够大,大于你的项目中的所有PHP文件的总和。设置值取值范围最小值是 200,最大值在 PHP 5.5.6 之前是 100000,PHP 5.5.6 及之后是 1000000。也就是说在200到1000000之间。
opcache.max_accelerated_files=4000
;设置缓存的过期时间(单位是秒),为0的话每次都要检查
opcache.revalidate_freq=60
;从字面上理解就是“允许更快速关闭”。它的作用是在单个请求结束时提供一种更快速的机制来调用代码中的析构器,从而加快PHP的响应速度和PHP进程资源的回收速度,这样应用程序可以更快速地响应下一个请求。把它设置为1就可以使用这个机制了。
opcache.fast_shutdown=1
;如果启用(设置为1),OPcache会在opcache.revalidate_freq设置的秒数去检测文件的时间戳(timestamp)检查脚本是否更新。如果这个选项被禁用(设置为0),opcache.revalidate_freq会被忽略,PHP文件永远不会被检查。这意味着如果你修改了你的代码,然后你把它更新到服务器上,再在浏览器上请求更新的代码对应的功能,你会看不到更新的效果强烈建议你在生产环境中设置为0,更新代码后,再平滑重启PHP和web服务器。
opcache.validate_timestamps=0
;开启Opcache File Cache(实验性), 通过开启这个, 我们可以让Opcache把opcode缓存缓存到外部文件中, 对于一些脚本, 会有很明显的性能提升.这样PHP就会在/tmp目录下Cache一些Opcode的二进制导出文件, 可以跨PHP生命周期存在.
opcache.file_cache=/tmp
模块安装结果
[root@localhost ~]# docker exec phpfpm74-v1.01 /bin/bash -c "php -m"
[PHP Modules]
bcmath
bz2
calendar
Core
ctype
curl
date
dom
exif
fileinfo
filter
ftp
gd
gettext
gmp
hash
iconv
intl
json
ldap
libxml
mbstring
mcrypt
memcached
mongodb
mysqli
mysqlnd
odbc
openssl
pcntl
pcre
PDO
pdo_mysql
pdo_pgsql
pdo_sqlite
pdo_sqlsrv
pgsql
Phar
posix
readline
redis
Reflection
session
shmop
SimpleXML
soap
sockets
sodium
SPL
sqlite3
sqlsrv
standard
swoole
sysvsem
sysvshm
tokenizer
xml
xmlreader
xmlrpc
xmlwriter
xsl
yaf
Zend OPcache
zip
zlib
[Zend Modules]
Zend OPcache
Docker单独构建Nginx镜像
docker pull nginx:1.25.1
docker run -itd --name nginx1.25.1-tmp nginx:1.25.1
docker exec nginx1.25.1-tmp /bin/bash -c 'cat /etc/issue'
Debian GNU/Linux 12 \n \l
进入容器查看默认配置
docker exec -it nginx1.25.1-tmp /bin/bash
拷贝出来:
mkdir /root/recycle_bin/nginx1.25.1
docker cp nginx1.25.1-tmp:/etc/nginx /root/recycle_bin/nginx1.25.1
/bin/cp -ap /root/recycle_bin/nginx1.25.1/nginx/* /opt/docker/nginx_cfg/
Docker单独构建Redis镜像
docker pull redis:7.0.11
docker run -itd --name redis7.0.11-tmp redis:7.0.11
docker exec redis7.0.11-tmp /bin/bash -c 'cat /etc/issue'
Debian GNU/Linux 12 \n \l
进入容器查看默认配置
docker exec -it redis7.0.11-tmp /bin/bash
没有发现redis的配置,整个容器找遍了都没有,奇怪,默认采用的配置没有显形的?
默认情况下,redis启动后的配置文件路径是/etc/redis/redis.conf或/usr/local/etc/redis/redis.conf,但也可能都不是,数据文件主目录是/data
以配置文件方式启动
redis-server /usr/local/etc/redis/redis.conf
在创建容器时指定配置例:
docker run -d --privileged=true -p 6379:6379 -v /docker/redis/conf/redis.conf:/etc/redis/redis.conf -v /docker/redis/data:/data --name redis-test redis redis-server /etc/redis/redis.conf --appendonly yes
可从Redis官网(redis.io)下载同版本源码包,采用里面的配置。在容器中对应路径是/usr/local/etc/redis,宿主机对应/opt/docker/redis_cfg
下载和安装Compose
发行版查看:https://github.com/docker/compose/releases
$ sudo curl -L "https://github.com/docker/compose/releases/download/v2.19.1/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
注意版本的选择,要安装其他版本的 Compose,请替换版本。
$ sudo chmod +x /usr/local/bin/docker-compose
$ sudo ln -s /usr/local/bin/docker-compose /usr/bin/docker-compose
测试是否安装成功:
docker-compose --version
准备dockerfile文件和docker-compose.yml文件,docker-compose.yml文件:
cd ~/sh; mkdir Dockerfiles; cd Dockerfiles
mkdir {php,nginx,redis}
文件目录如下
/Dockerfiles
├── php
│ ├── php_Dockerfile
│ └── php.ini
├── nginx
│ ├── nginx_Dockerfile
│ └── default.conf
├── redis
│ ├── redis_Dockerfile
└── docker-compose.yml
一般都忌讳数据库用docker跑,所以mysql一般仍单独部署,redis如果有持久化数据,也单独部署,接下来部署的redis视为无持久化数据的。
nginx的Dockerfile内容:
FROM nginx:1.25.1
MAINTAINER Fisher “N”
RUN mkdir /opt/web
php的Dockerfile内容:
FROM tmtcha/php:7.4.33-fpm-v1.01
redis的Dockerfile内容:
FROM redis:7.0.11
MAINTAINER Fisher ““N””
#ENV http_proxy proxyurl
创建数据持久化目录
mkdir -p /opt/docker/{nginx_cfg,nginx_log,php_cfg,php_log,redis_cfg,redis_log} /opt/web
docker-compose.yml文件内容
version: "2.7"
services:
nginx:
build:
context: ./nginx
dockerfile: ./nginx_Dockerfile
container_name: "nginx1.25.1"
# restart: on-failure
ports:
- "80:80"
- "443:443"
volumes:
- "/opt/docker/nginx_cfg:/etc/nginx"
- "/opt/docker/nginx_log:/var/log/nginx"
- "/opt/web:/opt/web"
healthcheck:
test: [ "CMD", "curl", "-f", "http://localhost:80" ]
interval: 1m30s
timeout: 7s
retries: 3
start_period: 40s
networks:
custom_bridge_net:
ipv4_address: 10.1.4.2
dns:
- 114.114.114.114
- 223.5.5.5
ulimits:
nproc: 65535
nofile:
soft: 20000
hard: 40000
logging:
driver: json-file
options:
max-size: "50m" # 单个文件大小为50m
max-file: "10" # 最多10个文件
php:
build:
context: ./php
dockerfile: ./php_Dockerfile
container_name: "phpfpm74-v1.01"
# restart: on-failure
ports:
- "9000:9000"
volumes:
- "/opt/web:/opt/web"
- "/opt/docker/php_cfg:/usr/local/etc"
- "/opt/docker/php_log:/usr/local/var/log"
healthcheck:
test: [ "CMD", "curl", "-f", "http://localhost:9000" ]
interval: 1m30s
timeout: 7s
retries: 3
start_period: 40s
networks:
custom_bridge_net:
ipv4_address: 10.1.4.3
dns:
- 114.114.114.114
- 223.5.5.5
ulimits:
nproc: 65535
nofile:
soft: 20000
hard: 40000
logging:
driver: json-file
options:
max-size: "50m" # 单个文件大小为50m
max-file: "10" # 最多10个文件
redis:
build:
context: ./redis
dockerfile: ./redis_Dockerfile
container_name: "redis7.0.11"
# restart: on-failure
ports:
- "6379:6379"
healthcheck:
test: [ "CMD", "redis-cli", "ping" ]
interval: 1m30s
timeout: 7s
retries: 3
start_period: 40s
volumes:
- "/opt/docker/redis_cfg/redis.conf:/usr/local/etc/redis/redis.conf"
- "/opt/redis/var:/data"
command:
redis-server /usr/local/etc/redis/redis.conf
networks:
custom_bridge_net:
ipv4_address: 10.1.4.4
dns:
- 114.114.114.114
- 223.5.5.5
ulimits:
nproc: 65535
nofile:
soft: 20000
hard: 40000
logging:
driver: json-file
options:
max-size: "50m" # 单个文件大小为50m
max-file: "10" # 最多10个文件
networks:
custom_bridge_net:
ipam:
driver: default
config:
- subnet: "10.1.4.0/24"
gateway: 10.1.4.1
Compose编排构建
运行下列命令构建,即可自动完成端口绑定、挂载、链接等操作
docker-compose up
构建网络加速
Docker Compose在构建时,使用网络加速(代理)
重新构建前清理现场
一键删除docker-compose镜像和容器示例
docker stop $(docker ps -a -q)
docker rm $(docker ps -a -q)
docker rmi $(docker images -q | grep -v f0d2ed79caf3) # 删除所有镜像但保留镜像f0d2ed79caf3
清除docker镜像缓存
默认情况下,如果已经拉去了某个镜像,即使已经删了该镜像,但是再次拉取还是会取缓存数据,下面执行清除本地docker缓存:
docker system prune
WARNING! This will remove:
- all stopped containers
- all networks not used by at least one container
- all dangling images
- all dangling build cache
或
docker system prune --volumes 该命令清除:
所有停止的容器
所有不被任何一个容器使用的网络
所有不被任何一个容器使用的volume
所有无实例的镜像 再次拉取镜像,输出
项目启停和查看
后台运行
docker-compose up -d
查看容器运行状态
docker-compose ps
停止该项目运行
docker-compose stop
和外部网络通信
发现6379端口不通,经排查,修改redis配置,添加密码认证,protected-mode设为no,仍不可连,iptables没有阻止,firewall的trusted区域默认没有起作用,或可添加富规则到public区域生效后可连了:
firewall-cmd --permanent --zone=public --add-rich-rule='rule family="ipv4" source address="来源IP" port protocol="tcp" port="6379" accept'
Mysql环境
独立部署,可参考基于RHEL8或RHEL9的RPM包构建部署:https://blog.csdn.net/ynz1220/article/details/135533982 https://blog.csdn.net/ynz1220/article/details/135535296