0. 前言
[技术源于艺术, 艺术源于生活]
-
这是我第一次发布程序相关的技术文章, 10年前发表过很多关于3dsmax和maya的技术文章
-
有人无端转载我的文章, 所以这里留一个我的联系方式, 欢迎讨论 邮箱: kekuer@gmail.com qq: 5513219
1. 背景
在我的文章中已经多次提到alpine, 轻量, 全面, 最好的docker系统镜像, 我目前已经广泛使用到生产环境, 主要好处是在降低自docker registry的磁盘暂用(目前我使用的是aws s3), 并且降低本地镜像构建push到online的registry的速度, 减少了部署所花费的不必要时间消耗.
2. 准备
2.1. rsync的使用
在alpine中rsync是有apk安装包, 只需要apk --update add rsync 即可安装 (在alpine 3.3中提供的是3.1.1版本的rsync)
2.2. alpine的官方源地址
alpine的官方wiki中提供了一篇制作镜像的文章, 我也是参考该文章完成本地镜像制作 How to setup a Alpine Linux mirror 在该文章中可以找到alpine源的同步地址: rsync://rsync.alpinelinux.org/alpine/
2.3. 了解alpine源目录结构
通过查看alpine现有官方源 可以了解alpine源目录结构, 方便在同步的时候排除不使用的资源, 比如: v2.x的早期版本, 减少同步时间和磁盘消耗.
2.4. 使用lighttpd驱动http
在alpine中lighttpd是有apk安装包, 只需要apk --update add lighttpd 即可安装 官方在这里选择了lighttpd, 我认为主要因为其配置简单; 按照以前的项目实施, lighttpd主要应用在文件下载服务器上, 因此也算对味. 根据自己的经验, 可以使用nginx或者apache来驱动, 该文章不再赘述.
2.5. 使用supervisor驱动2个应用在同一个docker container
在alpine中supervisor是有apk安装包, 只需要apk --update add supervisor 即可安装 为什么会有它? 文章后面会有介绍
3. 实施
3.1. 使用rsync同步alpine官方提供的源
3.1.1. 启动参数
rsync 比较简单, 通过--help选项可以查看到所有的选项, rsync官方描述都很清晰, 我这里只对我们需要使用的几个参数做介绍:
a) -p (preserve permissions): 保持同步源的文件权限, 也就是原来是文件是0664, 同步过来也是0664
b) -r (recurse into directories): 就是递归目录, 保持所有子目录内文件同步
c) -u (skip files that are newer on the receiver)
d) -a (archive mode; equals -rlptgoD (no -H,-A,-X))
e) --progress (show progress during transfer) 用来查看同步进度
f) --delete (delete extraneous files from destination dirs) 删除同步目录中在源中不存在的文件
g) --timeout (set I/O timeout in seconds) 设置同步中I/O的超时时间(秒)
h) delay-updates (put all updated files into place at transfer's end) 文件同步完成后才将文件放入同步目录, 这点比较重要, 防止apk文件有错
i) --delete-after (receiver deletes after transfer, not during)
j) --hard-links (preserve hard links) 同步硬链接
k) --exclude (exclude files matching PATTERN) 禁止匹配的文件同步
3.1.2. exclude文件配置
具体的不需要同步的文件匹配符, 可以根据你自己的需求来指定, 我只关心>=3.3的x86_64版本的apk, 测试时候会使用edge, latest-stable, 所有我的exclude配置文件如下:
v2.*/
v3.0/
v3.1/
v3.2/
armhf/
x86/
综上: 我们需要执行的bash命令是:
/usr/bin/rsync \
-prua \
--progress \
--exclude-from /conf/exclude \
--delete \
--timeout=120 \
--delay-updates \
--delete-after \
--hard-links
3.2. lighttpd驱动http
lighttpd 配置也比较简单, 分为启动参数和配置参数(lighttpd.conf), 我这里只对我们需要使用的几个参数做介绍:
3.2.1. 启动参数
a) -f (filename of the config-file) 指定配置文件
b) -D (don't go to background (default: go to background)) 保持在前端运行, 主要用于后期构建docker镜像用
3.2.2. 配置文件lighttpd.conf
# 申明变量
var.basedir = "/var/www"
var.statedir = "/var/lib/lighttpd"
# http监听端口
server.port = 8089
# 加载必要模块
server.modules = (
"mod_access",
"mod_setenv",
"mod_accesslog"
)
# 包含文件扩展名解析mime类型conf文件
include "/etc/lighttpd/mime-types.conf"
# 配置服务器日志到控制台, 用于docker收集日志
server.errorlog = "/dev/stderr"
accesslog.filename = "/dev/stdout"
# 指定http根路径, 这里用到顶部申明的变量
server.document-root = var.basedir + "/alpine"
# 指定pid路径
server.pid-file = "/var/run/lighttpd.pid"
# 允许列出文件列表
dir-listing.activate = "enable"
# 禁止对隐藏文件列表
dir-listing.hide-dotfiles = "enable"
# 禁止访问以下目录及文件 (对该项目意义不大, 只是习惯加上好点, 也就用了一个官方默认的参数)
url.access-deny = ("~", ".inc")
# 强制所有缓存都需要到服务器验证, 主要避免本地缓存的错误(就自己用, 也不用太考虑服务器压力了), 具体的可以看下http header中Cache-control部分的介绍
setenv.add-response-header += ("Cache-Control" => "must-revalidate")
综上: 我们需要执行的bash命令是:
/usr/sbin/lighttpd -D -f /conf/lighttpd.conf
3.3. supervisor启动多任务
需要思考一个问题: 做成1个镜像(包含rsync和lighttpd)还是2个镜像(分开, 然后使用docker-compose启动)?
我选择的是做一个镜像, 因为毕竟这个不属于生产环境的应用, 因为我习惯在本地打包镜像然后push到生产环境, 然后再run, 所以我选择生成1个镜像. 生成一个镜像的话, 我们需要keepalive这2个进程, 最容易想到的就是supervisor
3.3.1. 启动参数
a) -n (run in the foreground) 保持在前端运行, 主要用于docker镜像, (也可以在配置文件配置)
b) -c (configuration file) 指定配置文件
3.3.2. 配置文件supervisord.conf
[supervisord]
; 启动到前端, 用于docker
nodaemon=true
; 设置pid文件路径
pidfile=/var/run/supervisord.pid
; 配置rsync
[program:rsync]
; 配置日志输出到控制台, 用于docker收集日志
stdout_logfile=/dev/stdout
; 去掉日志rotation
stdout_logfile_maxbytes=0
autorestart=true
command=/usr/bin/rsync -prua --progress --exclude-from /conf/exclude --delete --timeout=120 --delay-updates --delete-after --hard-links rsync://rsync.alpinelinux.org/alpine/ /var/www/alpine
; 配置lighttpd
[program:lighttpd]
; 配置日志输出到控制台, 用于docker收集日志
stdout_logfile=/dev/stdout
; 去掉日志rotation
stdout_logfile_maxbytes=0
autorestart=true
command=/usr/sbin/lighttpd -D -f /conf/lighttpd.conf
综上: 我们需要执行的bash命令是:
/usr/bin/supervisord -c /conf/supervisord.conf
3.4. 制作docker镜像
3.4.1. Dockerfile
FROM alpine:3.3
MAINTAINER Alpine Mirror Docker Maintainers "kekuer@gmail.com"
RUN echo "http://127.0.0.1:8098/main" > /etc/apk/repositories && \
apk --update add rsync lighttpd supervisor
ADD conf /conf
EXPOSE 8089
ENTRYPOINT ["/usr/bin/supervisord"]
CMD ["-c", "/conf/supervisord.conf"]
echo "http://127.0.0.1:8098/main" > /etc/apk/repositories 这句根据自己情况添加, 我是因为我之前已经有一个本地镜像
3.4.2. 运行container
docker run -id --name alpine-mirror -p 8089:8089 funwun.io/alpine-mirror:1.0
根据情况可以挂载alpine镜像目录, 避免删除container后失去镜像 docker run -id -v /alpine:/var/www/alpine --name alpine-mirror -p 8089:8089 funwun.io/alpine-mirror:1.0
4. 结语
涉及的知识点还是比较多, 每个应用都可以写一本书, 我们这里只是选择了要用的部分, 具体的使用大家可以多学习一下相关知识