前言
前面提到过我们可以用commit命令进行镜像的构建,但是这样的方式太不灵活。接下来我会对用Dockerfile文件构建镜像做讲解。
一、dockerfile常用指令
FROM 基础镜像,一切从这里开始
格式:
FROM <image>
FROM <image>:<tag>
FROM <image>@<digest>
示例:
FROM mysql:5.6
MAINTAINER 镜像是谁写的,姓名+邮箱号
格式:
MAINTAINER <name>
示例:
MAINTAINER bertwu
MAINTAINER xxx@163.com
MAINTAINER bertwu <xxx@163.com>
RUN 运行的命令
RUN用于在构建镜像时执行命令,其有以下两种命令执行方式:
shell执行
格式:
RUN <command>
exec执行
格式:
RUN ["executable", "param1", "param2"]
示例:
RUN ["executable", "param1", "param2"]
RUN apk update
RUN ["/etc/execfile", "arg1", "arg1"]
ADD 添加压缩包内容,比如tomcat
格式:
ADD <src>... <dest>
ADD ["<src>",... "<dest>"] 用于支持包含空格的路径
示例:
ADD hom* /mydir/ # 添加所有以"hom"开头的文件
ADD hom?.txt /mydir/ # ? 替代一个单字符,例如:"home.txt"
ADD test relativeDir/ # 添加 "test" 到 `WORKDIR`/relativeDir/
ADD test /absoluteDir/ # 添加 "test" 到 /absoluteDir/
WORKDIR 镜像的工作目录
格式:
WORKDIR /path/to/workdir
示例:
WORKDIR /a (这时工作目录为/a)
WORKDIR b (这时工作目录为/a/b)
WORKDIR c (这时工作目录为/a/b/c)
VOLUME 挂载的目录
格式:
VOLUME ["/path/to/dir"]
示例:
VOLUME ["/data"]
VOLUME ["/var/www", "/var/log/apache2", "/etc/apache2"]
EXPOSE 暴露端口
CMD 指定这个容器启动运行时的命令,只有最后一个会生效,可被替代
ENTRYPOINT 指定这个容器启动运行时的命令,可以追加命令
格式:
ENTRYPOINT ["executable", "param1", "param2"] (可执行文件, 优先)
ENTRYPOINT command param1 param2 (shell内部命令)
示例:
FROM ubuntu
ENTRYPOINT ["ls", "/usr/local"]
CMD ["/usr/local/tomcat"]
之后,docker run 传递的参数,都会先覆盖cmd,然后由cmd 传递给entrypoint ,做到灵活应用
注:ENTRYPOINT与CMD非常类似,不同的是通过docker run执行的命令不会覆盖ENTRYPOINT,
而docker run命令中指定的任何参数,都会被当做参数再次传递给CMD。
Dockerfile中只允许有一个ENTRYPOINT命令,多指定时会覆盖前面的设置,
而只执行最后的ENTRYPOINT指令。
通常情况下, ENTRYPOINT 与CMD一起使用,ENTRYPOINT 写默认命令,当需要参数时候 使用CMD传参
ONBUILD 当构建一个被继承dockerfile的时候,就会运行ONBUILD的指令。触发指令
(ONBUILD是一个特殊的指令它后面跟的是其它指令,比如 RUN, COPY 等,而这些指令,在当前镜像构建时并不会被执行。
只有当以当前镜像为基础镜像,去构建下一级镜像的 时候才会被执行)
COPY 类似ADD,将我们的目录拷贝到镜像中
ENV 构建的时候设置环境变量
格式:
ENV <key> <value> #<key>之后的所有内容均会被视为其<value>的组成部分,因此,一次只能设置一个变量
ENV <key>=<value> ... #可以设置多个变量,每个变量为一个"<key>=<value>"的键值对,如果<key>中包含空格,可以使用\来进行转义,也可以通过""来进行标示;另外,反斜线也可以用于续行
示例:
ENV myName John Doe
ENV myDog Rex The Dog
ENV myCat=fluffy
二、dockerfile构建kafka镜像步骤
1.下载构建镜像所需的安装包
1.为了方便管理我新建了一个flumedockerfile的文件夹(为什么是叫flume文件夹呢…因为当时想创建kafka文件夹的但是后来没注意就创建成了flume的),之后会把下载文件放在该文件夹下。分别下载jdk和kafka的安装包,如图:
2.通过vim Dockerfile
命令进入Dockerfile文件,然后可以开始写命令了。
2.编写dockerfile文件内容
FROM centos:centos7
#以centos7镜像为基础镜像,在该镜像基础上镜像构建
ADD jdk-8u202-linux-x64.tar.gz /usr/local/java
#将下载好的jdk安装包添加到 /usr/local/java路径下
ENV JAVA_HOME /usr/local/java/jdk1.8.0_202
#设置java环境变量
ENV CLASSPATH $JAVA_HOME/lib:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
ENV PATH $JAVA_HOME/bin:$PATH
# 安装 flume
ADD kafka_2.12-2.8.0.tgz /usr/local/
RUN mv /usr/local/kafka_2.12-2.8.0 /usr/local/kafka
#容器创建的时候把/usr/local/kafka_2.12-2.8.0 移到/usr/local/kafka的自定义目录下
ENV KAFKA_HOME /usr/local/kafka
#设置kafka的环境变量
ENV PATH $KAFKA_HOME/bin:$PATH
WORKDIR /usr/local/kafka
#设置工作目录
3.通过build命令生成镜像
dockerfile文件别写完成后保存退出,然后在通过build命令去生成一个镜像,该命令会自动扫描动dockerfile文件。
docker build -t 镜像名 .
顺带提一句,如果想让容器创建后就自动运行里面的服务可以在dockerfile文件编写CMD命令。比如我要启动flume,那么就找到flume启动文件的bin目录
,例如我的启动文件在/usr/local/flume/bin下,那么就这样编写CMD命令。
CMD /usr/local/flume/bin/flume-ng agent -c ./conf/ -f ./conf/xxxx.properties -n agent