一、Dockerfile介绍
Dockerfile是一个包含创建镜像所有命令的文本文件,通过docker build命令可以根据Dockerfile的内容构建镜像。
一般的,Dockerfile分为四部分:基础镜像信息、维护者信息、镜像操作指令和容器启动时执行指令,其中,‘#’为Dockerfile中的注释。
二、常用指令
- FROM
所有Dockerfile都必须以FROM命令开始。FROM命令会指定镜像基于哪个基础镜像创建,接下来的命令也会基于这个基础镜像。FROM命令可以多次使用,表示创建多个镜像。
FROM <image>:<tag>
如果本地没有指定的镜像,则会从对应的镜像仓库pull镜像下来,不指定具体镜像仓库,则会从docker hub公共仓库拉取。
如果没有指定标签tag,则默认使用latest标签。
- MAINTAINER
设置该镜像的作者。
MAINTAINER <author name>
- ENV
设置环境变量,使用键值对,并且该环境变量可以被后续的Dockerfile命令使用
ENV <key>:<value> #设置一个变量
ENV <key1>:<value1> \ #设置多个变量,可以通过"\"换行
<key2>:<value2>
- ARG
设置构建环境的环境变量,只在构建容器时生效,在将来容器运行时是不会存在这些环境变量的且在构建时可以使用--build-arg=
来指定参数。具体用法如下:
ARG <key>=<value>
不要因此就是用ARG保存密码之类的信息,因为docker history可以看到所有的值。
- WORKDIR
设置后续Dockerfile命令,像RUN、CMD、ENTRYPOINT、COPY、ADD的工作目录,如果WORKDIR不存在,会自动创建。
WORKDIR /path/workdir
- ADD
复制本地主机文件、目录或者远程文件URLS添加到容器指定路径中,它又两个参数和。source是本地绝对路径或者是Dockerfile所在的相对路径,destination是容器内的路径且如果dest路径不存在,会自动创建对应的目录;如果dest路径不是以斜线结尾,文件会以普通文件形式写入到目标。
如果复制的是压缩文件,会自动解压。
ADD <src> <destination>
- COPY
COPY复制文件或者目录,并且添加到容器指定路径中。用法同ADD,不同的是不能指定远程文件URL、不会解压压缩包。
COPY <src> <destination>
- EXPOSE
设置容器暴露的端口。
EXPOSE <port>
运行容器时,需要配合使用-p或-P参数进行端口映射,映射到宿主机
- USER
设置RUN/CMD/ENTRYPOINT的用户名或UID。
USER <name>
- VOLUME
设置容器的挂载点。
VOLUME ["/data/]
VOLUME /data1 /data2
- RUN
在构建镜像时执行命令。RUN指令会在新创建的镜像上添加新的镜像层。
RUN <command> # shell风格,即shell命令
RUN ["exec","parm1","parm2"] # exec风格
- CMD
设置容器启动命令。
CMD ["exec","parm1","parm2"]
CMD ["parm1","parm2"] # 为ENTRYPOINT提供参数列表
CMD <command>
- ENTRYPOINT
设置容器的入口程序。具体用法如下:
ENTRYPOINT ["exec","parm1","parm2"]
ENTRYPOINT command parm1 parm2
ENTRYPOINT与CMD的区别在于,ENTRYPOINT的等级更高,一个Dockerfile里边可以既有ENTRYPOINT又有CMD,这个时候CMD后面的命令会作为ENTRYPOINT的参数传递。
推荐ENTRYPOINT和CMD都使用exec的方式来构建。
如果Dockerfile中指定了多条CMD,只有最后一条会被执行;
每个Dockerfile只能有一个ENTRYPOINT,当多个ENTRYPOINT时,只有最后一个生效。
三、Dockerfile示例
基于CentOS7.9,安装并运行redis
- 同级目录文件
$ tree
.
├── CentOS-Base.repo #YUM源,可自行下载阿里云镜像源
├── Dockerfile
├── epel.repo #YUM源,可自行下载阿里云镜像源
├── redis-6.2.12.tar.gz #redis安装包
└── redis.conf #redis配置文件
- redis配置文件,使用默认即可
$ vim redis. conf
bind 0.0.0.0
protected-mode yes
port 6379
tcp-backlog 511
timeout 0
tcp-keepalive 300
daemonize no
supervised no
pidfile /var/run/redis_6379.pid
loglevel notice
logfile "/usr/local/redis/log/redis.log"
databases 16
always-show-logo yes
save 900 1
save 300 10
save 60 10000
stop-writes-on-bgsave-error yes
rdbcompression yes
rdbchecksum yes
dbfilename dump.rdb
dir /usr/local/redis/data
replica-serve-stale-data yes
replica-read-only yes
repl-diskless-sync no
repl-diskless-sync-delay 5
repl-disable-tcp-nodelay no
replica-priority 100
requirepass 123456
lazyfree-lazy-eviction no
lazyfree-lazy-expire no
lazyfree-lazy-server-del no
replica-lazy-flush no
appendonly no
appendfilename "appendonly.aof"
appendfsync everysec
no-appendfsync-on-rewrite no
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
aof-load-truncated yes
aof-use-rdb-preamble yes
lua-time-limit 5000
slowlog-log-slower-than 10000
slowlog-max-len 128
latency-monitor-threshold 0
notify-keyspace-events ""
hash-max-ziplist-entries 512
hash-max-ziplist-value 64
list-max-ziplist-size -2
list-compress-depth 0
set-max-intset-entries 512
zset-max-ziplist-entries 128
zset-max-ziplist-value 64
hll-sparse-max-bytes 3000
stream-node-max-bytes 4096
stream-node-max-entries 100
activerehashing yes
client-output-buffer-limit normal 0 0 0
client-output-buffer-limit replica 256mb 64mb 60
client-output-buffer-limit pubsub 32mb 8mb 60
hz 10
dynamic-hz yes
aof-rewrite-incremental-fsync yes
rdb-save-incremental-fsync yes
- Dockerfile
$ vim Dockerfile
FROM centos:centos7.9.2009
MAINTAINER real
RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && echo 'Asia/Shanghai' >/etc/timezone \
rm -f /etc/yum.repos.d/*
COPY CentOS-Base.repo epel.repo /etc/yum.repos.d/
RUN yum clean all && yum makecache && yum install -y gcc make
ADD redis-6.2.12.tar.gz /tmp/
RUN cd /tmp/redis-6.2.12 && make MALLOC=libc && make PREFIX=/usr/local/redis install && \
mkdir -p /usr/local/redis/{data,etc,log}
COPY redis.conf /usr/local/redis/etc/
ENTRYPOINT exec /usr/local/redis/bin/redis-server /usr/local/redis/etc/redis.conf
EXPOSE 6379
- 构建镜像
注意命令最后的点`.`,是基于当前目录的Dockerfile进行构建
$ docker build -t redis:latest .
- 基于redis镜像启动容器
$ docker run -d --name redis-server -p 16379:6379 redis
-d:后台运行容器
--name:为容器指定一个名称
-p:指定端口映射。格式为:宿主机端口:容器端口
最后跟镜像名称
- 查看容器
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
e25d95579784 redis "/bin/sh -c 'exec /u…" 6 seconds ago Up 5 seconds 0.0.0.0:16379->6379/tcp, :::16379->6379/tcp redis-server
- 使用redis客户端登录redis容器,进行验证
$ redis-cli -h 127.0.0.1 -p 16379
127.0.0.1:16379> auth 123456
OK
127.0.0.1:16379>
四、最佳实践
- 减少镜像层数,尽量把一些指令合在一起;
- 注意清理镜像构建的中间产物,比如一些安装包在安装之后就把它删掉
- 注意优化网络请求,使用yum源时,用一些网络比较好的源站点,可节约时间,减少失败率
- 尽量去构建缓存,把一些不变的东西或者变动较少的东西放在前面,因为不变的东西可以被缓存,如果不想使用缓存,则可以在docker build时添加–no-cache=true选项