1. 查找镜像
不要使用docker search查找镜像,search只能搜索到镜像名称,并不能找到所有的标签名,也无法得知镜像使用方法。应该前往官方镜像网站查找需要的镜像。
官方镜像网址:https://hub.docker.com/explore/
查找镜像可以使用搜索功能,只需要输入镜像名称即可,不要把标签也添加上,否则搜索不到结果。
镜像中有不同的标签,表明的软件的版本以及镜像的基础环境,例如redis镜像,有如下的版本:
图中标识redis共有11个版本镜像,每个版本的镜像存在多个标签。包括3.0和3.2版本,32位和64位的使用环境,alpine和window等基础镜像环境等。
根据自身的需要选择合适自己的镜像
2. 帮助文档
使用镜像不是简单的run运行就可以,很多时候还需要添加一些必要的参数才能跑起来,如何找到这些参数应该如何配置呢?查看帮助文档,在镜像页面的下方通常都是帮助文档,镜像相关信息。下面是redis镜像的帮助文档
3. 镜像源码
如果看帮助文档找不到自己想要看的帮助,或者想要知道镜像的整个构建使用过程,可以查看镜像的源码。
在镜像列表中,选择自己想要使用的镜像,点击旁边的Dockerfie连接,将会跳转到该镜像的git项目中。
在项目页面,我们可以看到redis的Dokcerfile文件,了解镜像做了什么操作,还可以找到镜像的启动脚本entrypoint.sh等
下载源码,我们也可以自己编译redis镜像。
4. 定制自己的镜像
如果镜像官方的镜像不能满足你的特别要求,这时候你需要自己定制镜像,下面我拿我自己定制的redis镜像做个例子。
我的需求是redis可以配置maxclient,maxmemory等参数 首先参考官网的镜像帮助文档,redis的配置文件放在容器/usr/local/etc/redis/redis.conf文件夹下。
编写redis.conf文件
#daemonize yes
pidfile /var/run/redis.pid
port 6379
tcp-backlog 511
timeout 300
tcp-keepalive 300
loglevel notice
logfile ""
databases 16
save 900 1
save 300 10
save 60 10000
stop-writes-on-bgsave-error yes
rdbcompression yes
rdbchecksum yes
dbfilename dump.rdb
dir /data/
slave-serve-stale-data yes
slave-read-only yes
repl-disable-tcp-nodelay no
slave-priority 100
# maxmemory <bytes>
# maxmemory-policy volatile-lru
# maxmemory-samples 3
appendonly no
appendfilename "appendonly.aof"
appendfsync everysec
no-appendfsync-on-rewrite no
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
lua-time-limit 5000
slowlog-log-slower-than 10000
slowlog-max-len 128
notify-keyspace-events ""
hash-max-ziplist-entries 512
hash-max-ziplist-value 64
list-max-ziplist-entries 512
list-max-ziplist-value 64
set-max-intset-entries 512
zset-max-ziplist-entries 128
zset-max-ziplist-value 64
activerehashing yes
client-output-buffer-limit normal 0 0 0
client-output-buffer-limit slave 256mb 64mb 60
client-output-buffer-limit pubsub 32mb 8mb 60
hz 10
aof-rewrite-incremental-fsync yes
注意,redis.conf文件中有两个需要注意的地方:
- daemonize参数设置为no 或者注释掉,如果设置为yes,则容器启动就会结束,因为没有前台进程。
- bind 不要设置为127.0.0.1 注释掉,测试发现设置127.0.0.1会出现服务访问被拒绝的情况。
编写自己的启动脚本entrypoint.sh
在原redis镜像的entrypoint.sh做修改。
#!/bin/sh
set -e
# first arg is `-f` or `--some-option`
# or first arg is `something.conf`
if [ "${1#-}" != "$1" ] || [ "${1%.conf}" != "$1" ]; then
set -- redis-server "$@"
fi
# allow the container to be started with `--user`
if [ "$1" = 'redis-server' -a "$(id -u)" = '0' ]; then
chown -R redis .
exec gosu redis "$0" "$@"
fi
#环境变量替换部分参数
set_config(){
if [ $TIMEOUT ]; then
sed -i 's/^timeout .*/timeout '"$TIMEOUT"'/g' /usr/local/etc/redis/redis.conf
fi
if [ $DATABASES ]; then
sed -i 's/^databases .*/databases '"$DATABASES"'/g' /usr/local/etc/redis/redis.conf
fi
if [ $MAX_CLIENTS ]; then
sed -i 's/^# maxclients.*/maxclients'"$MAX_CLIENTS"'/g' /usr/local/etc/redis/redis.conf
fi
#内存限制设置
local limit_in_bytes=$(cat /sys/fs/cgroup/memory/memory.limit_in_bytes)
if [ "$limit_in_bytes" -ne "9223372036854771712" ]; then
local limit_in_megabytes=$(expr $limit_in_bytes \/ 1048576)
sed -i 's/^# maxmemory .*/maxmemory '"$limit_in_megabytes"'/g' /usr/local/etc/redis/redis.conf
#开启内存限制最好指定清理策略
if [ $MAX_MEMORY_POLICY ];
then
sed -i 's/^# maxmemory-policy.*/maxmemory-policy '"$MAX_MEMORY_POLICY"'/g' /usr/local/etc/redis/redis.conf
else
sed -i 's/^# maxmemory-policy.*/maxmemory-policy volatile-lru/g' /usr/local/etc/redis/redis.conf
fi
fi
if [ $MAX_MEMORY ]; then
sed -i 's/^# maxmemory .*/maxmemory '"$MAX_MEMORY"'/g' /usr/local/etc/redis/redis.conf
#开启内存限制最好指定清理策略
if [ $MAX_MEMORY_POLICY ];
then
sed -i 's/^# maxmemory-policy.*/maxmemory-policy '"$MAX_MEMORY_POLICY"'/g' /usr/local/etc/redis/redis.conf
else
sed -i 's/^# maxmemory-policy.*/maxmemory-policy volatile-lru/g' /usr/local/etc/redis/redis.conf
fi
fi
}
set_config && exec "$@"
脚本中set_config方法是我进行参数替换的部分,通过传入环境变量替换配置文件中的参数。注意,这里会存在两个问题。
- 容器重复启动,配置文件是否变化?entrypoint.sh是每次启动容器都会执行的脚本,第一次启动容器,和第n次启动容器,执行脚本的结果是否会导致配置文件不一样?
- 权限问题,redis创建了一个redis用户用于执行redis进程,而dockerfile创建的文件夹是root权限的,那么sed命令无法在该文件夹下使用,因为redis用户无法在该文件夹下创建临时文件。(这个问题可以在Dockerfile中解决)
编写Dockfile文件
FROM redis:3.0.7
MAINTAINER shijieming@lutongnet.com
COPY redis.conf /usr/local/etc/redis/redis.conf
RUN chown -R redis /usr/local/etc/redis
COPY docker-entrypoint.sh /usr/local/bin/docker-entrypoint.sh
CMD [ "redis-server" , "/usr/local/etc/redis/redis.conf" ]
- 使用了redis:3.0.7作为基础镜像
- 添加本地的redis.conf文件到容器相应目录
- 修改配置文件所在文件夹权限
- 添加本地的启动脚本,这里会覆盖原有的docker-entrypoint.sh
- 启动命令 使用配置文件启动
执行下面的命令生成镜像
$ docker build .
Sending build context to Docker daemon 10.75 kB
Step 1/6 : FROM redis:3.0.7
---> c44fa74ead88
Step 2/6 : MAINTAINER shijieming@lutongnet.com
---> Using cache
---> bfdd1371df83
Step 3/6 : COPY redis.conf /usr/local/etc/redis/redis.conf
---> Using cache
---> 0933f3eeba04
Step 4/6 : RUN chown -R redis /usr/local/etc/redis
---> Using cache
---> e2cd58419d3b
Step 5/6 : COPY docker-entrypoint.sh /usr/local/bin/docker-entrypoint.sh
---> Using cache
---> 88413869eef5
Step 6/6 : CMD redis-server /usr/local/etc/redis/redis.conf
---> Using cache
---> 082aa959aa4f
Successfully built 082aa959aa4f
$ docker tag 082aa959aa4f myredis:3.0.7
通过命令生成了自己定义的myredis:3.0.7镜像。
当然除了基于官方镜像做修改,还可以使用直接修改官方的Dockerfile文件等,也可以自行编写Dockerfile文件。