Docker容器服务编排实践
关注公众号 后端搬运工《Docker容器服务编排实践》
之前 博客 经常因为云厂商服务器优惠到期,不得不更换云服务器,而整个博客系统依赖很多,导致迁移部署的成本很大。
通过容器服务编排技术让整个系统上 Docker 后,再更换云服务器厂商时,就可以做到快速平滑迁移了。 Docker 环境云服务器
服务器的操作系统是 CentOS,我们选用 Docker Compose 作为容器编排工具。 安装 Docker# 1.删除旧的Docker版本 sudo yum remove docker docker-client docker-client-latest docker-common docker-latest docker-latest-logrotate docker-logrotate docker-engine # 2.添加Docker源 sudo yum install -y yum-utils sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo # 3.安装Docker sudo yum install docker-ce docker-ce-cli containerd.io sudo yum install docker-ce-20.10.1 docker-ce-cli-20.10.1 containerd.io # 4.启动Docker sudo systemctl start docker # 5.查看Docker版本 docker -v Docker version 20.10.1, build 831ebea 安装 Docker Compose# 1.获取docker-compose脚本 sudo curl -L "https://github.com/docker/compose/releases/download/1.27.4/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose # 2.增加可执行权限 sudo chmod +x /usr/local/bin/docker-compose sudo ln -s /usr/local/bin/docker-compose /usr/bin/docker-compose # 3.查看版本 docker-compose --version docker-compose version 1.27.4, build 40524192 项目改造调整目录结构
之前的目录结构较为单一,需调整项目目录结构。调整后的目录结构如下: ├── _config.yml # Hexo配置文件 ├── disqus # Disqus评论 ├── themes # Hexo主题 │ └── yilia # hexo-theme-yilia主题 ├── source # 文章.md文件 ├── public # Hexo发布后的静态资源文件 ├── dockerfiles # Dockerfile文件 │ ├── nginx │ ├── nodejs │ └── php ├── docker-compose.yml # 容器编排配置 ├── docker.env # Docker环境变量文件 ├── docker.example.env # Docker环境变量示例文件 ├── network-override.yml # 容器编排配置(特殊网络) └── package.json # Hexo依赖包
其中, disqus 和 yilia 目录分别对应 disqus-php-api 和 hexo-theme-yilia 这 2 个子项目,并采用 submodule 模式管理这些源代码。
在 submodule 模式下, clone 和 pull 命令会有一些变化,分别为 git clone --recursive https://github.com/fan-haobai/blog.git
和 git pull && git submodule foreach git pull origin master 。 编排容器
本博客系统,主要依赖 NodeJS 、 PHP 、 Nginx 环境,因此分别构建 3 个容器。 配置 docker-compose.yml
Docker Compose 会根据 docker-compose.yml 配置文件,来自动编排容器。配置如下: version: "3" services: nginx: restart: always build: ./dockerfiles/nginx ports: - "80:80" - "443:443" volumes: # 博客源代码 - "/var/www/blog:/var/www/blog" # HTTPS证书 - "/var/www/ssl/certs:/var/www/ssl/certs" # Nginx配置 - "$PWD/dockerfiles/nginx/conf.d:/etc/nginx/conf.d" command: /bin/bash /start.sh env_file: - docker.env extra_hosts: - "raw.githubusercontent.com:199.232.96.133" container_name: "nginx" nodejs: build: ./dockerfiles/nodejs ports: - "4000:4000" volumes: - "/var/www/blog:/var/www/blog" container_name: "nodejs" php: restart: always build: ./dockerfiles/php expose: - "9000" volumes: - "/var/www/blog:/var/www/blog" container_name: "php"
其中, services 下为需要编排的 nodejs 、 php 、 nginx 容器服务。每个容器服务都可以灵活配置,常见的配置参数如下: restart:容器退出时,是否重启 build:构建容器 Dockerfile 文件所在的目录 ports:映射端口 volumes:挂载目录 command:容器启动后执行的命令 env_file:环境变量文件 extra_hosts:域名IP映射 container_name:容器名称
Docker Compose 支持多配置文件,且为覆盖关系。因此将 ssl-override.yml 作为获取 HTTPS 证书时启动容器的配置文件。 配置 docker.env
环境变量统一配置在 docker.env 文件中,并增加示例环境文件 docker.example.env 。环境变量目前较少,如下: # 是否启用HTTPS证书 ENABLE_SSL=true # 支持HTTPS协议的域名 SSL_DOMAINS=fanhaobai.com,www.fanhaobai.com 构建 Dockerfile
Dockerfile 文件统一放在 dockerfiles 目录下,并分别建立 nodejs 、 php 、 nginx 文件夹。 NODEJS
该容器下需要安装 git 、 npm 。Dockerfile 文件如下: FROM node:12-alpine RUN echo "Asia/Shanghai" > /etc/timezone && echo "https://mirrors.ustc.edu.cn/alpine/v3.9/main/" > /etc/apk/repositories && npm config set registry https://registry.npm.taobao.org && apk add --no-cache git && npm install hexo-cli -g ADD *.sh / RUN chmod 777 /*.sh EXPOSE 4000 ENTRYPOINT ["sh", "/start.sh"]
其中, start.sh 为容器的启动脚本,主要作用为生成静态资源文件。内容如下: #!/bin/bash cd /var/www/blog # 更新代码 git pull && git submodule foreach git pull origin master # 生成静态资源 npm install --force # hexo clean hexo g hexo s PHP
该容器基于官方的基础镜像,安装一些必要的扩展。Dockerfile 文件如下: FROM php:7.3.7-fpm-alpine3.9 RUN echo "https://mirrors.aliyun.com/alpine/v3.9/main/" > /etc/apk/repositories && echo "https://mirrors.aliyun.com/alpine/v3.9/community/" >> /etc/apk/repositories # 安装扩展 RUN apk add --no-cache $PHPIZE_DEPS && apk add --no-cache libstdc++ libzip-dev vim && apk update && apk del $PHPIZE_DEPS RUN apk add --no-cache freetype libpng libjpeg-turbo freetype-dev libpng-dev libjpeg-turbo-dev && apk update && docker-php-ext-configure gd --with-freetype-dir=/usr/include/ --with-jpeg-dir=/usr/include/ --with-png-dir=/usr/include/ && docker-php-ext-install -j$(nproc) gd && docker-php-ext-install -j$(nproc) opcache && docker-php-ext-install -j$(nproc) bcmath # 配置文件 RUN mv "$PHP_INI_DIR/php.ini-production" "$PHP_INI_DIR/php.ini" ADD conf.d/* $PHP_INI_DIR/conf.d/
其中, conf.d 下为 php 的配置文件。 NGINXDockerfile 文件
该容器基于官方的基础镜像,并安装 cron 、 wget 、 python 。Dockerfile 文件如下: FROM nginx:latest # 安装cron等 RUN sed -i s@/deb.debian.org/@/mirrors.aliyun.com/@g /etc/apt/sources.list && apt-get update && apt-get install -y cron wget python # 启动脚本和配置 ADD *.sh / ADD nginx.conf /etc/nginx/nginx.conf # HTTPS证书生成脚本 ADD ssl/* /var/www/ssl/ RUN chmod +x /var/www/ssl/*.sh RUN chmod 777 -R /var/log/nginx
其中, conf.d 下为 nginx 的配置文件, ssl 下为 HTTPS 证书的生成脚本。 HTTPS 证书生成脚本
ssl 下的 init_ssl.sh 为首次获取 HTTPS 证书脚本, refresh_cert.sh 为更新 HTTPS 证书脚本。
其中, init_ssl.sh 脚本内容如下: #!/bin/bash echo "### Stoping nginx ..." docker-compose down # 启动容器 echo "### Starting nginx ..." docker-compose -f docker-compose.yml -f ssl-override.yml up --force-recreate --build -d # 是否启动完成 until [ "`docker inspect -f {{.State.Running}} nginx`"=="true" ]; do echo "### Wait nginx docker start ..." sleep 0.1; done; # 生成HTTPS证书 echo "### Gen nginx ssl ..." docker exec nginx /bin/bash /var/www/ssl/refresh_cert.sh # 重启nginx echo "### Restart nginx ..." docker exec nginx nginx -s reload
ssl-override.yml 会覆盖 docker-compose.yml 中的环境变量,因此会将环境变量 ENABLE_SSL 设置为 false ,并将 php 解析到 127.0.0.1 ,以确保 nginx 容器在首次能成功启动。
而 refresh_cert.sh 脚本内容如下: #!/bin/bash dir="/var/www/ssl" certs_dir="$dir/certs" mkdir -p $certs_dir cd $certs_dir if [ -z "$SSL_DOMAINS" ]; then echo "### Domains is empty" exit 1 fi echo "### Starting ssl ..." openssl genrsa 4096 > account.key openssl genrsa 4096 > domain.key domains=`echo "DNS:$SSL_DOMAINS" | sed "s/,/&DNS:/g"` echo "### Gen domain key, domains: $domains ..." openssl req -new -sha256 -key domain.key -subj "/" -reqexts SAN -config <(cat /etc/ssl/openssl.cnf <(printf "[SAN] subjectAltName=$domains")) > domain.csr echo "### Download acme_tiny script ..." wget https://raw.githubusercontent.com/diafygi/acme-tiny/master/acme_tiny.py -O acme_tiny.py echo "### Gen chained cert ..." python acme_tiny.py --account-key account.key --csr domain.csr --acme-dir $dir/challenges/ > signed.crt || exit openssl dhparam -out dhparams.pem 2048 wget -O - https://letsencrypt.org/certs/lets-encrypt-x3-cross-signed.pem > intermediate.pem cat signed.crt intermediate.pem > chained.pem echo "### End ssl ..."
其中, SSL_DOMAINS 为环境变量文件 docker.env 中配置需要支持 HTTPS 的域名。 容器启动脚本
在该容器启动后,会执行 start.sh 脚本。其内容如下: #!/bin/bash dir="/var/www/ssl" mkdir -p "$dir/challenges" # 是否启用HTTPS if [ "$ENABLE_SSL" = "false" ]; then # 修改nginx配置, 不启用HTTPS sed -i "/https/d" /etc/nginx/nginx.conf else # 每2个月更新一次, 并重启nginx容器 ssl_cron="0 0 1 */2 * $dir/refresh_cert.sh && nginx -s reload 2>> /var/log/acme_tiny.log" crontab -l | { cat; echo "$ssl_cron"; } | crontab - fi # 前台启动 nginx -g "daemon off;"
其中需要注意,当不启用 HTTPS 协议时,需要将 Nginx 配置修改为不启用 HTTPS;而启用时,会添加每 2 个月重新生成证书的定时任务。 nginx 也需要改为前台启动模式,否则容器会因没有前台程序而自动退出。 部署
前面的一切都准备就绪后,部署就异常简单了,后续再迁移时,也只需要简单做部署这一步就好了。 配置环境变量 cp docker.example.env docker.env 获取HTTPS证书 /bin/bash dockerfiles/nginx/ssl/init_ssl.sh
注意:如果无需支持HTTPS协议,则跳过此步骤,并将环境变量 ENABLE_SSL 修改为 false 。 启动所有容器 docker-compose up --force-recreate --build -d
如果一切顺利,那么运行 docker ps -a 命令就能看到已成功启动的容器,如下: docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES b0307bac08d7 blog_nodejs "sh /start.sh" 2 days ago Up 2 days 0.0.0.0:4000->4000/tcp nodejs e8ef7a1e9271 blog_nginx "/docker-entrypoint.…" 2 days ago Up 2 days 0.0.0.0:80->80/tcp nginx af7baad788c5 blog_php "docker-php-entrypoi…" 2 days ago Up 2 days 9000/tcp php
通过 www.fanhaobai.com 域名也可以直接访问了。
春节我在岗万家灯火团圆时忠诚坚守护航安确保足够富裕水深,你轮可以在401浮下线。新年快乐,秦皇岛船舶交管中心655号值班员提醒您谨慎驾驶,注意安全,一路顺航。655是麻国栋在交管中心的值班编号,今年,也是他在值班台上度
春节我在岗文昌气田海油人守护万家灯火1月22日,农历大年初一,中国海油湛江分公司文昌9293103气田(下文简称文昌气田)的员工生活楼被装扮得焕然一新。漂亮的灯笼火红的春联大大的福字,处处洋溢着新年的喜庆。文昌气田位
邵东公安平安春节风警无处不在红网时刻新闻1月30日讯(通讯员刘元)为确保群众度过一个喜庆祥和的新春佳节,邵东市公安局科学部署,全面加强重点要害部位的管控力度,严厉打击各类违法犯罪,在辖区重点部位开展巡逻防控工
问记者丨零下53!边防官兵是怎样过年的?北纬53,零下53!今年春节,新华社解放军分社记者梅世雄采访了驻守在祖国最北端北纬53的黑龙江省漠河市北部战区陆军某边防旅北极哨所,在零下53的极寒条件下,与官兵一起巡逻,一起过节
玉渊谭天一个春节,读懂中国经济的世界意义刚刚过去的这个中国春节,让一些看法变了。春节前,中国防疫转段,让一些外媒对中国经济复苏产生质疑,纽约时报称中国面临崎岖痛苦的经济复苏之路。春节期间,中国经济的火热景象,让来自世界的
兔年说兔中国家兔起源?古代人眼中的兔子?第十二十三届全国政协委员袁靖的分享袁靖我是动物考古学家。按照动物考古学的研究,到现在为止,在已经发表的全国三百余处遗址出土动物遗存的研究结果中,发现出土兔子遗存的遗址有将近八十处,虽然还不到出土动物遗存的遗址总数的
文旅消费活力回归,春节假期大鹏接待游客同比增长133一年春作首,万象始更新。兔年新春,深圳市大鹏新区旅游接待人数和旅游收入较去年同期实现了双增长,其中,假期期间接待游客人数同比增长133。42,文旅消费活力回归,文旅市场强劲复苏。据
玉渊谭天丨一个春节,读懂中国经济的世界意义刚刚过去的这个中国春节,让一些看法变了。春节前,中国防疫转段,让一些外媒对中国经济复苏产生质疑,纽约时报称中国面临崎岖痛苦的经济复苏之路。春节期间,中国经济的火热景象,让来自世界的
2月1日,故宫博物院对教师和本科专科学生免费开放故宫博物院网站北京故宫博物院视觉中国图关于2023年教师和本科院校专科院校学生主题免费开放日的公告2023年2月1日(周三),故宫博物院对教师和本科院校专科院校学生免费开放。申请人
猛禽之王金雕展翅抓羊,场面超震撼!科幻网1月29日讯(金恺祎)近日,有摄影爱好者在北京房山拍到了金雕捕食的震撼一幕。先是一只大金雕和两只羊对峙,突然又飞出来第二只,在拍摄到的画面中,金雕张开双翅拎着一只羊飞速掠过,
零工驿站让就业更有温度天门日报讯(融媒体记者陈飞)我原本在外地工作,现在为了方便照顾小孩,想回到家乡工作,有合适的请帮我推荐一下。1月27日上午,在2023年春季大型现场招聘会零工驿站展台前,欧阳女士填