由于项目服务器要从centos 6升级到centos 7,但是在升级过程中,发现web项目的php在加载自行编写的C扩展时,运行在centos 7总是崩溃,但是直接改C扩展预计要花比较长的时间,可能会延误服务器升级,遂计划基于centos 6,将php构造成docker 镜像来运行。正所谓当翻越山峰耗时,那么绕过去不失为一个办法,最终目的都是抵达终点。
于是有了本篇文章,从docker安装、镜像构建,到docker-compose管理容器,最后基于systemctl管理docker-compose异常重启。
1)yum安装
yum install -y yum-utils vim // 安装基础工具
yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo //添加软件源信息
yum -y install docker-ce
systemctl enable docker --now //启动docker并设置为开机自启
2)二进制安装(推荐,更加灵活)
wget https://download.docker.com/linux/static/stable/x86_64/docker-20.10.21.tgz
tar -zxvf docker-20.10.21.tgz
mkdir -p /usr/local/docker-20.10.21
mv docker/* /usr/local/docker-20.10.21
ln -sv /usr/local/docker-20.10.21/* /usr/bin/
groupadd -r docker
[root@ali ~]# cat /usr/lib/systemd/system/docker.service
[Unit]
Description=Docker Application Container Engine
Documentation=https://docs.docker.com
After=network-online.target firewalld.service
Wants=network-online.target
[Service]
Type=notify
# the default is not to use systemd for cgroups because the delegate issues still
# exists and systemd currently does not support the cgroup feature set required
# for containers run by docker
ExecStart=/usr/bin/dockerd --config-file=/etc/docker/daemon.json
ExecReload=/bin/kill -s HUP $MAINPID
# Having non-zero Limit*s causes performance problems due to accounting overhead
# in the kernel. We recommend using cgroups to do container-local accounting.
LimitNOFILE=infinity
LimitNPROC=infinity
LimitCORE=infinity
# Uncomment TasksMax if your systemd version supports it.
# Only systemd 226 and above support this version.
#TasksMax=infinity
TimeoutStartSec=0
# set delegate yes so that systemd does not reset the cgroups of docker containers
Delegate=yes
# kill only the docker process, not all processes in the cgroup
KillMode=process
# restart the docker process if it exits prematurely
Restart=on-failure
RestartSec=3s
StartLimitBurst=3
StartLimitInterval=60s
[Install]
WantedBy=multi-user.target
[root@ali ~]# cat /etc/docker/daemon.json
{
"data-root": "/home/docker/data-root",
"pidfile": "/home/docker/run/docker.pid",
"log-level": "info",
"registry-mirrors": ["http://hub-mirror.c.163.com","https://registry.docker-cn.com"] #docker镜像源
}
systemctl enable docker --now
systemctl restart docker
docker配置相关
docker命令
docker-compose 是用于定义和运行多容器 Docker 应用程序的工具,通过一个配置文件来管理多个Docker容器,在配置文件中,所有的容器通过services来定义,然后使用docker-compose脚本来启动,停止和重启应用,和应用中的服务以及所有依赖服务的容器,非常适合组合使用多个容器进行开发的场景。这样就可以替代复杂的shell脚本来管理多个容器。
二进制文件获取
linux下载
curl -L https://github.com/docker/compose/releases/download/2.14.2/docker-compose-`uname -s`-`uname -m` -o /usr/bin/docker-compose
指令说明
FROM #基础镜像,我们要制作的镜像常常是依赖某个基础镜像来实现的,这些基础镜像常见的如centos,ubatu,alpine,harbox,debian等,其中alpine很小,安全。
这些镜像到docker官方仓库搜索即可,选择相应的版本,如:FROM centos:6.6 。
COPY #从上下文目录中复制文件或者目录到容器里指定路径。如:COPY ./package/usr/lib64/phpmath.so /usr/lib64/phpmath.so。
RUN #用于在基础镜像中执行后面跟着的命令行命令。如:RUN mkdir -p /usr/local/php/ 。
CMD #类似于 RUN 指令,用于运行程序,但二者运行的时间点不同:1)CMD 在docker run 时运行;2)RUN 是在 docker build。如果有多条仅最后一条生效。该指令所启动的程序即容器的主进程,其退出容器也会退出,所以该指令的命令应当是常驻进程。
FROM centos:6.6
COPY ./package/usr/lib64/phpmath.so /usr/lib64/phpmath.so
COPY ./package/usr/lib64/libserialize.so /usr/lib64/libserialize.so
COPY ./package/usr/lib64/protocolbuffers.so /usr/lib64/protocolbuffers.so
COPY ./package/usr/lib64/redis.so /usr/lib64/redis.so
COPY ./package/usr/lib64/mysqli.so /usr/lib64/mysqli.so
COPY ./package/php5 /usr/local/
COPY ./dockerphp5/usr/local/php/etc/php-fpm.conf /usr/local/php/etc/php-fpm.conf
RUN mkdir -p /home/php/fpm/ #fpm 日志目录
RUN mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.backup
COPY ./dockerphp5/etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo
RUN yum clean all && yum makecache
RUN yum -y install vixie-cron
RUN yum -y install crontabs
#一些定时脚本
COPY ./dockerphp5/etc/crontab /etc/crontab
RUN mkdir -p /etc/cron.minutely/
COPY ./dockerphp5/etc/cron.minutely/* /etc/cron.minutely/
RUN mkdir -p /etc/cron.hourly/
COPY ./dockerphp5/etc/cron.hourly/* /etc/cron.hourly/
RUN mkdir -p /etc/cron.daily/
COPY ./dockerphp5/etc/cron.daily/* /etc/cron.daily/
EXPOSE 9000
CMD ["/usr/bin/phpfpmd.sh"] #/usr/bin/phpfpmd.sh有多条命令,仅最后一条是常驻的
[root@ali ~]# cat /usr/bin/phpfpmd.sh
#!bin/bash
/etc/init.d/crond restart
/usr/local/php/sbin/php-fpm -y /usr/local/php/etc/php-fpm.conf -g /usr/local/php/var/run/php-fpm.pid
docker build -t php:5.4.7 -f ./dockerphp5/Dockerfile . #其中-t指定镜像名称和tag(版本)
如果顺利执行完,就可以看到镜像了
[root@ali ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
php 5.4.7 360997ecc130 3 weeks ago 852MB
centos 6.6 368c96d786ae 3 years ago 203MB
指令说明
version: '3'
services:
php5:
image: "php:5.4.7" #指定镜像
ports:
- "127.0.0.1:9000:9000"
volumes: #指定目录挂载
- "/usr/local/web:/usr/local/web" #项目代码目录
- "/home/web:/home/web" #项目日志等目录
- "/etc/docker/cron.minutely:/etc/cron.minutely"
- "/etc/docker/cron.hourly:/etc/cron.hourly"
- "/etc/docker/cron.daily:/etc/cron.daily"
- "/etc/localtime:/etc/localtime" #时间与宿主机一致
extra_hosts: #向容器/etc/hosts添加域名
- "redis.link.cn:200.200.172.106"
- "mysql.link.cn:200.200.172.108"
container_name: "phpfpmd" #容器名称
此时可以通过/usr/bin/docker-compose -f /etc/docker/docker-compose.yml up 来启动容器了,相比较docker run -itd -p 9000:9000 -v xxx:xxx --add-host xxx:xxx --name phpfpmd php:5.4.7 简洁多了,特别是容器多的时候,但是无法解决开机自启动,没有看门狗的问题,这个可以利用systemctl来解决
指令说明
[Unit]
Description=php-fpm
#Documentation=nothing
After=network-online.target docker.service
Wants=network-online.target
Requires=docker.service
[Service]
#service type
Type=simple #服务类型,1)simple(默认值):ExecStart字段启动的进程为主进程 2)forking:ExecStart字段将以fork()方式启动,此时父进程将会退出,子进程将成为主进程
#3)oneshot:类似于simple,但只执行一次,Systemd 会等它执行完,才启动其他服务 4)dbus:类似于simple,但会等待 D-Bus 信号后启动
#5)notify:类似于simple,启动结束后会发出通知信号,然后 Systemd 再启动其他服务,fixme:这种需要启动程序实现sd_notify 6)idle:类似于simple,但是要等到其他任务都执行完,才会启动该服务。一种使用场合是为让该服务的输出,不与其他服务的输出相混合
# for php-fpm container control,
ExecStart=/usr/bin/docker-compose -f /etc/docker/docker-compose.yml up
#ExecReload=
ExecStop=/usr/bin/docker-compose -f /etc/docker/docker-compose.yml stop
# kill only the docker process, only exec ExecStop
KillMode=none
# softdog :restart the php-fpm process if it exit
Restart=on-failure #异常时会重启
RestartSec=3s #每3s检查一次
StartLimitBurst=3
StartLimitInterval=60s
[Install]
WantedBy=multi-user.target
编写完成放到/usr/lib/systemd/system/目录下,即/usr/lib/systemd/system/phpfpmd.service
systemctl daemon-reload
systemctl enable phpfpmd
systemctl restart phpfpmd
至此一个完整的docker容器就完成了