目录
1. Dockfile是什么
2. Dockerfile的基本组成
2.1 FROM
2.2 MAINTAINER
2.3 RUN
2.4 COPY
2.5 ADD
2.6 EXPOSE
2.7 WORKDIR
2.8 ONBUILD
2.9 USER
2.10 VOLUME
2.11 CMD
2.12 ENTRYPOINT
3. dockerfile示例
3.1 准备
3.2 将该目录上传至linux
3.3 构建镜像
3.4 通过镜像运行容器
1. Dockfile是什么
docker推荐使用dockerfile的定义文件和docker build命令来构建镜像。dockerfile使用基本的基于DSL(面向领域语言)语法的指令来构建Docker镜像。另一种创建Docker镜像的方式是使用docker commit,不推荐使用。
2. Dockerfile的基本组成
dockerfile有一系列指令和参数组成,每条指令都必须为大写,执行时按顺序从上到下执行,所以应该根据需要合理安排指令的顺序。
Dockerfile的基本组成及说明:
组成 | 说明 |
基础镜像信息 | FROM |
维护者信息 | MAINTAINER |
镜像操作指令 | RUN、(COPY/ADD)、EXPOSE、WORKDIR、ONBUILD、USER、VOLUME等 |
容器启动时执行指令 | CMD、ENTRYPOINT |
2.1 FROM
指定基础镜像,如:
FROM ubuntu:18.04
2.2 MAINTAINER
指定该镜像的作者及电子邮件等信息
MAINTAINER lisen "xxxxx@163.com"
2.3 RUN
在镜像内部执行的指令,如安装软件,配置基础环境等,可用\进行换行
RUN echo 'hello' > /usr/local/file.txt
也可以使用exec格式,RUN ["命令", "参数1","参数2"], 如:
RUN ["apt-get", "install", "-y", "ubuntu"]
2.4 COPY
将主机的文件复制到镜像中,如果目的目录不存在,docker会自动创建所需目录结构。注意:该命令只是单纯的复制,并不会做文件的提取解压工作。
COPY file.txt /usr/local
注意:需复制的文件或目录必须要放在Dockerfile文件的同级目录下。
2.5 ADD
将宿主机文件复制到镜像,该命令与COPY命令作用和用法是一样的,但ADD命令会对压缩文件做解压和提取操作(tar,gzip等)
2.6 EXPOSE
暴露镜像的端口供主机做端口映射,运行镜像时使用-P参数将镜像端口与宿主机随机端口或指定端口做映射。
示例:
EXPOSE 8080
可以通过docker port查看到端口的映射情况。
2.7 WORKDIR
WORKDIR指令用来在从镜像创建一个新容器时,在容器内部设置一个工作目录,ENTRYPOINT和/或CMD指定的程序会在这个目录下执行。
我们可以使用该指令为Dockerfile中后续的一系列指令设置工作目录,也可以为最终的容器设置工作目录。
示例:
WORKDIR /opt/webapp/db
RUN bundle install
WORKDIR /opt/webapp
ENTRYPOINT [ "rackup" ]
这里,我们将工作目录切换为/opt/webapp/db后运行了bundle install命令,之后又将工作目录设置为/opt/webapp,最后设置了ENTRYPOINT指令来启动rackup命令。
可以通过-w标志在运行时覆盖工作目录,如代码清单4-57所示。
代码清单4-57 覆盖工作目录
$ sudo docker run -ti -w /var/log ubuntu pwd
/var/log
该命令会将容器内的工作目录设置为/var/log。
2.8 ONBUILD
当一个包含ONBUILD命令的镜像被用作其他镜像的基本镜像时,ONBUILD指令将执行。
例如:base-image
FROM ubuntu
ONBUILD ADD . /var/www
......
当使用base-image作基础镜像创建imageA时,
FROM base-image
......
则base-image基础镜像的 ONBUILD指令会执行
2.9 USER
指定镜像以什么用户执行
USER user01
2.10 VOLUME
向基于镜像创建的容器添加卷。一个卷是可以存在于一个或者多个容器内的特定的目录,这个目录可以绕过联合文件系统,并提供如下共享数据或者对数据进行持久化的功能。
示例:
#使用VOLUME 指令向容器添加volume
VOLUME /data
#可以添加多个
VOLUME ["/data1","/data2"] #添加多个
注意:VOLUME指令不能挂载宿主机中指定的目录,这是为了保证Dockerfile的可移植性,因为不能保证所有的宿主机都有对应的目录。
2.11 CMD
CMD指令用于指定一个容器启动时要运行的命令,这有点儿类似于RUN指令,只是RUN指令是指定镜像被构建时要运行的命令,而CMD是指定容器被启动时要运行的命令。
例如:
$ sudo docker run -i -t jamtur01/static_web /bin/true
在Dockerfile中以下的CMD指令是等效的
CMD ["/bin/true"]
可以为要运行的命令指定参数,以下代码清单
CMD ["/bin/bash", "-l"]
这里我们将-l参数传递给了/bin/bash命令。
需要注意的是使用docker run命令可以覆盖CMD指令,如果我们在Dockerfile里指定了CMD指令,而同时在docker run命令行中也指定了要运行的命令,命令行中指定的命令会覆盖Dockerfile中的CMD指令。
2.12 ENTRYPOINT
ENTRYPOINT指令与CMD指令很相似,它们的区别在于ENTRYPOINT指令提供的命令不容易在启动容器时被覆盖,docker run命令行中指定的任何参数都会当作参数再次传给ENTRYPOINT命令。
ENTRYPOINT命令的一个示例:
ENTRYPOINT ["/usr/sbin/nginx"]
与CMD命令相似,ENTRYPOINT命令可以使用数组形式指定参数,如以下代码清单:
ENTRYPOINT ["/usr/sbin/nginx", "-g", "daemon off;"]
若我们构建镜像,并将ENTRYPOINT设置为ENTRYPOINT["/usr/sbin/nginx"],用docker build构建镜像,代码清单如下:
$ sudo docker build -t="jamtur01/static_web" .
然后用如下命令启动容器:
sudo docker run –t -i jamtur01/static_web -g "daemon off;"
则命令行参数-g "daemon off;"会传递给ENTRYPOINT指定的命令。在这里该命令为/usr/sbin/nginx -g "daemon off;"。该命令会以前台运行的方式启动Nginx守护进程,此时这个容器就会作为一台Web服务器来运行
3. dockerfile示例
该示例通过Dockerfile的方式构建一个安装了jdk的镜像。
3.1 准备
这个方式 是通过git命令行创建 也可创建文本文件将扩展名给去除
创建一个目录,在该目录中放入jdk,并创建一个Dockerfile文件。如图:
下载素材包
天翼云盘 珍藏美好生活 家庭云|网盘|文件备份|资源分享(访问码:mpe8)
Dockerfile文件如下:
#0.vi Dockerfile进入编辑模式
#1.指定基础镜像,并且必须是第一条指令
FROM ubuntu:latest
#2.指明该镜像的作者和其电子邮件
MAINTAINER zs "zs@qq.com"
#3.在构建镜像时,指定镜像的工作目录,之后的命令都是基于此工作目录,如果不存在,则会创建目录
WORKDIR /usr/local/java
#4.一个复制命令,把jdk安装文件复制到镜像中,语法:ADD <src>... <dest>,注意:jdk*.tar.gz使用的是相对路径
ADD jdk-8u151-linux-x64.tar.gz /usr/local/java/
#5.配置环境变量
ENV JAVA_HOME=/usr/local/java/jdk1.8.0_151
ENV CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
ENV PATH=$JAVA_HOME/bin:$PATH
#容器启动时需要执行的命令
#CMD ["java","-version"]
注:在构建镜像时基础镜像请使用指定版本,而不要使用latest
3.2 将该目录上传至linux
上传文件包含
3.3 构建镜像
登录linux,进入dockerfilejdk目录,通过docker build 构建镜像
3.4 通过镜像运行容器
查看我们刚才创建的镜像
root@ubuntu:/home/lisen/dockerfilejdk# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
jdk1.8-container latest f61711334bc6 13 seconds ago 449MB
通过镜像运行容器
root@ubuntu:/# docker run -it jdk1.8-container /bin/bash
root@ba5158079806:/usr/local/java#
4. 一点建议
- 精简镜像用途:尽量让每个镜像的用途都比较集中单一,避免构造大而复杂、多功能的镜像
- 选用合适的基础镜像:容器的核心是应用,选择过大的父镜像(如Ubuntu系统镜像)会造成最终生成应用镜像的膝肿,推荐选用瘦身过的应用镜像或者较为小巧的系统镜像(alpine)