搜索 K
Appearance
博客正在加载中...
Appearance
Dockerfile 非常重要,在实际工作中,使用 Docker 绝不是敲敲一些常用命令即可。Dockerfile 几乎贯穿微服务的全部内容,务必掌握。
不要求能从头开始编写 Dockerfile,至少如果有个 Dockerfile 的模板,我们能够修改。
Dockerfile 是用来构建 Docker 镜像的文本文件,是由一条条构建镜像所需的指令和参数构成的脚本(类似 Linux 的 shell 脚本)。
之前我们给 Ubuntu 镜像安装了 vim 和 ifconfig 功能,然后通过 docker commit 功能,形成了一个新的镜像,这是一个加强版的镜像;
在简单的情况下,这样做是可以的;但后期我们会构建微服务镜像,有很多很多的配置,每次都 commit 的话,就很麻烦了;就好比执行 SQL 语句,每执行一条就要 commit 一次,不方便。
Dockerfile 可以一次性搞定,想要装什么功能,只需提供一个清单即可。
示意图:通过 Dockerfile 一次性完成镜像的构建
官网文档:Dockerfile reference
构建三步骤
Dockerfile 内容基础知识:
# 表示注释
Docker 执行 Dockerfile 的大致流程:
Dockerfile 是软件的原材料
Docker 镜像是软件的交付品
Docker 容器则可以认为是软件镜像的运行态,也即依照镜像运行的容器实例
Dockerfile 面向开发,Docker 镜像成为交付标准,Docker 容器则涉及部署与运维,三者缺一不可,合力充当 Docker 体系的基石。
我们之前使用的镜像,很多也是用 Dockerfile 的,例如 Tomcat。我们以 Tomcat 的 Dockerfile 为例,简单介绍下常用的保留字。
可以在 GitHub 上看到其 Dockerfile:里面有很多的关键字,在最后会有 run,然后会 expose 一个端口 8080,然后执行命令(Tomcat 的启动命令,catalina.sh)
FROM amazoncorretto:8-al2-jdk
ENV CATALINA_HOME /usr/local/tomcat
ENV PATH $CATALINA_HOME/bin:$PATH
RUN mkdir -p "$CATALINA_HOME"
WORKDIR $CATALINA_HOME
..........
# verify Tomcat Native is working properly
RUN set -eux; \
nativeLines="$(catalina.sh configtest 2>&1)"; \
nativeLines="$(echo "$nativeLines" | grep 'Apache Tomcat Native')"; \
nativeLines="$(echo "$nativeLines" | sort -u)"; \
if ! echo "$nativeLines" | grep -E 'INFO: Loaded( APR based)? Apache Tomcat Native library' >&2; then \
echo >&2 "$nativeLines"; \
exit 1; \
fi
EXPOSE 8080
CMD ["catalina.sh", "run"] 该文件可能很多行,不过不用担心,去掉注释后就没剩下多少了;而且也不要求从头开始编写,看得懂、能依样画葫芦即可。
指明基础镜像,当前新镜像是基于哪个镜像的(例如可以基于 Ubuntu),指定一个已经存在的镜像作为模板,第一条必须是 from。
镜像维护者的姓名和邮箱地址
容器构建时(docker build 时)需要运行的命令。两种格式:
RUN <命令行命令> ,等同于在终端执行 shell 命令,例如 RUN yum -y install vimRUN ["可执行文件", "参数1", "参数2"],例如 RUN ["./test.php", "dev", "offline"] 等价于 RUN ./test.php", "dev", "offline" 当前容器对外暴露出的端口(还记得运行容器时,可以指定端口映射的选项 -p 么)
指定该镜像以什么样的用户去执行,如果不指定,默认是 root
指定在创建容器后,终端默认登陆的进来工作目录。
比如我们进入 Tomcat 时,默认是去到了 /usr/local/tomcat 目录:
$ docker run -d -p 8080:8080 --name t1 tomcat
$ docker exec -it t1 bash
$ pwd
/usr/local/tomcat Dockerfile 也是这样配的:
ENV CATALINA_HOME /usr/local/tomcat
WORKDIR $CATALINA_HOME用来在构建镜像过程中设置环境变量
ENV MY_PATH /usr/mytest这个环境变量可以在后续的任何 RUN 指令中使用,这就如同在命令前面指定了环境变量前缀一样; 也可以在其它指令中直接使用这些环境变量,比如:
WORKDIR $MY_PATH配置容器数据卷,用于数据保存和持久化工作
可以将宿主机目录下指定的文件拷贝进镜像,且会自动处理 URL 和解压 tar 压缩包
例如要在镜像内装个 Java8,并且是通过解压安装的方式,就可以用该命令。
类似 ADD,拷贝文件和目录到镜像中。 将从构建上下文目录中 < 源路径 > 的文件/目录复制到新的一层的镜像内的 < 目标路径 > 位置。命令格式:
COPY src destCOPY ["src", "dest"]<src源路径>:源文件或者源目录
<dest目标路径>:容器内的指定路径, 路径不存在的话,会自动创建。
指定容器启动后的要干的事情。CMD 指令的格式和 RUN 类似,格式:
CMD <命令>CMD ["可执行文件", "参数1", "参数2"]CMD ["参数1", "参数2"...]。如果指定了 ENTRYPOINT 指令,那么 CMD 就只用来传参了(后面再说) 例如,Tomcat 最后启动的命令:CMD ["catalina.sh", "run"]Dockerfile 中可以有多个 CMD 指令,但只有最后一个生效。
CMD 会被 docker run 之后的参数替换。例如我们启动一个 Tomcat,带上 bash 操作:
docker run -it -p 8080:8080 --name t1 tomcat bash那么 Tomcat 就不会启动了,因为 CMD 命令替换了:
CMD 和 RUN 命令的区别:
也是用来指定一个容器启动时要运行的命令。类似于 CMD 指令,但是 ENTRYPOINT 不会被 docker run 后面的命令覆盖, 而且这些命令行参数会被当作参数送给 ENTRYPOINT 指令指定的程序
命令格式:
ENTRYPOINT ["<executeable>", "<param1>", "<param2>", ...]ENTRYPOINT 可以和 CMD 一起用,一般是变参才会使用 CMD ,这里的 CMD 等于是在给 ENTRYPOINT 传参。
当指定了 ENTRYPOINT 后,CMD 的含义就发生了变化,不再是直接运行其命令而是将 CMD 的内容作为参数传递给 ENTRYPOINT 指令,他两个组合会变成 <ENTRYPOINT> "<CMD>" 案例如下:假设已通过 Dockerfile 构建了 nginx:test 镜像:
FROM nginx;
ENTRYPOINT ["nginx", "-c"] # 定参
CMD ["/etc/nginx/nginx.conf"] # 变参
| 是否传参 | 按照 dockerfile 编写执行 | 传参运行 |
|---|---|---|
| Docker 命令 | docker run nginx:test | docker run nginx:test -c /etc/nginx/new.conf |
| 衍生出的实际命令 | nginx -c /etc/nginx/nginx.conf | nginx -c /etc/nginx/new.conf |
如果传参运行,相当于用自己传入的配置,覆盖 Dockerfile 中的默认配置。 优点:在执行 docker run 的时候可以指定 ENTRYPOINT 运行所需的参数。
注意:如果 Dockerfile 中如果存在多个 ENTRYPOINT 指令,仅最后一个生效。
| BUILD | Both | RUN |
|---|---|---|
| FROM | WORKDIR | CMD |
| MAINTAINER | USER | ENV |
| COPY | EXPOSE | |
| ADD | VOLUME | |
| RUN | ENTRYPOINT | |
| ONBUILD | ||
| .dockerignore | ||
| | ||
| |
讲了下常用保留字,可能有点不好理解,我们用实际例子来说明。
我们自定义一个镜像:mycentosjava8。要求在 Centos7 镜像基础上,安装 vim+ifconfig+jdk8 先下载 Centos 镜像:
docker pull centos:7如果是 Centos8 等镜像,可能会要额外设置一些 yum,这里不展开,建议用 Centos7,我们课程目的是学 Docker。
然后我们下载 Java 8:Java Downloads | Oracle,这里我们选择 x64 Compressed Archive 的版本(下载 Java 最新版的,这里是 8u381,后期可能有更新,没关系用最新版的即可)
接下来准备编写 Dockerfile 文件(注意 Dockerfile 文件,首字母得是大写的 D):
$ mkdir /myfile
$ cd /myfile
$ touch Dockerfile
$ pwd
/myfile
$ ll
总用量 136012
-rw-r--r-- 1 root root 0 9月 9 21:00 Dockerfile
-rwxr-x--- 1 root root 139273048 9月 9 21:00 jdk-8u381-linux-x64.tar.gz请自行将下载好的 Java 安装包挪到该目录。 然后在 Dockerfile 文件里粘贴如下内容:
FROM centos:7
MAINTAINER peterjxl<peterjxl@qq.com>
ENV MYPATH /usr/local
WORKDIR $MYPATH
#安装vim编辑器
RUN yum -y install vim
#安装ifconfig命令
RUN yum -y install net-tools
#安装java8及lib库
RUN yum -y install glibc.i686
RUN mkdir /usr/local/java
#ADD 是相对路径jar,把jdk-8u171-linux-x64.tar.gz添加到容器中,安装包必须要和Dockerfile文件在同一位置
ADD jdk-8u381-linux-x64.tar.gz /usr/local/java/
#配置java环境变量
ENV JAVA_HOME /usr/local/java/jdk1.8.0_381
ENV JRE_HOME $JAVA_HOME/jre
ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar:$JRE_HOME/lib:$CLASSPATH
ENV PATH $JAVA_HOME/bin:$PATH
EXPOSE 80
CMD echo $MYPATH
CMD echo "success--------------ok"
CMD /bin/bash 该 Dockerfile 里的内容,都是之前讲过的,稍微看看应该都能看懂。如果下载的 Java 版本比较新,注意修改第 21 行处的对应文件名,此外解压太 Java 压缩包后,目录名也要修改(第 25 行)
接下来我们构建该镜像,命令格式:docker build -t 新镜像名字:TAG .
选项 -t 是什么意思呢?查看下帮助,就是构建时要带的一个选项:
$ docker build --help
............
-t, --tag stringArray Name and optionally a tag (format: "name:tag")
--target string Set the target build stage to build
--ulimit ulimit Ulimit options (default []) 接下来我们开始构建,执行如下命令:
docker build -t centosjava8:1.5 . 安装完后,我们可以检查下镜像,可以看到我们自己的镜像大了不少,有 1.24G:
$ docker images centos*
REPOSITORY TAG IMAGE ID CREATED SIZE
centosjava8 1.5 9263eda71f21 2 minutes ago 1.24GB
centos 7 eeb6ee3f44bd 24 months ago 204MB接下来我们运行下该镜像,命令格式:docker run -it 新镜像名字:TAG
docker run -it centosjava8:1.5 接下来测试下,首先是登录后的位置:
# pwd
/usr/local vim 命令:
$ vim -version
VIM - Vi IMproved 7.4 (2013 Aug 10, compiled Dec 15 2020 16:44:08)
Garbage after option argument: "-version"
More info with: "vim -h" ifconfig 命令:
$ ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 172.17.0.4 netmask 255.255.0.0 broadcast 172.17.255.255
ether 02:42:ac:11:00:04 txqueuelen 0 (Ethernet)
RX packets 8 bytes 656 (656.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 0 bytes 0 (0.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536
inet 127.0.0.1 netmask 255.0.0.0
loop txqueuelen 1000 (Local Loopback)
RX packets 0 bytes 0 (0.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 0 bytes 0 (0.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0Java 版本:
$ java -version
java version "1.8.0_381"
Java(TM) SE Runtime Environment (build 1.8.0_381-b09)
Java HotSpot(TM) 64-Bit Server VM (build 25.381-b09, mixed mode)在 Ubuntu 镜像基础上,安装 vim,ifconfig 和 Java8 (完)