Docker | 第四章:Dockerfile简单介绍及使用
前言
前一章节,介绍了
Docker
常用的命令。在基本使用上,熟悉这些常用的命令基本上就够了。但在一些场景下,比如在部署SpringBoot
应用时,通常我们都是打成Jar
包,然后利用java
命令进行运行jar包。这个时候我们就能通过编写Dockerfile
进行自动化部署了(可能这个比喻不太恰当⊙﹏⊙‖∣)。总体来说,可利用Dockerfile
文件自定义镜像内容,改变原始镜像的一些行为,以满足个性化需求。
- Dockerfile介绍
- Dockerfile命令说明
- [FROM 指定基础镜像](#FROM 指定基础镜像)
- [LABEL 镜像元数据](#LABEL 镜像元数据)
- [ENV 设置环境变量](#ENV 设置环境变量)
- [VOLUME 定义匿名卷](#VOLUME 定义匿名卷)
- [COPY 复制文件](#COPY 复制文件)
- [ADD 更高级的复制文件](#ADD 更高级的复制文件)
- [EXPOSE 设置监听端口](#EXPOSE 设置监听端口)
- [ARG 设置构建参数](#ARG 设置构建参数)
- [RUN 执行命令](#RUN 执行命令)
- [CMD 启动时命令](#CMD 启动时命令)
- [ENTRYPOINT 启动默认命令](#ENTRYPOINT 启动默认命令)
- [WORKDIR 指定工作目录](#WORKDIR 指定工作目录)
- [USER 指定当前用户](#USER 指定当前用户)
- 其他命令
- 总结
- 最后
- 参考资料
- 老生常谈
Dockerfile介绍
Dockerfile是一个文本文件,里面包含了若干条指令,每条指令描述了构建镜像的细节。简单来说,它就是由一系列指令和参数构成的脚本文件,从而构建出一个新的镜像文件。
Dockerfile格式
简单来说,Dockerfile
格式一般如下:
# 注释
指令 [参数]
这里以一个修改Nginx
镜像首页为示例(此镜像使用说明详见:https://hub.docker.com/_/nginx/),简单说明:
# 注意:非注释第一行 必须以FROM 开头。
# FROM 指定基础镜像,即以此镜像作为基础
FROM nginx
# 设置元数据,利用 docker inspect [镜像名称|镜像ID],即可查看。
LABEL author="作者:oKong"
LABEL version="版本:v0.1"
LABEL desc="说明:修改nginx首页提示"
# 操作执行,这里直接修改了nginx的html的首页内容,/usr/share/nginx/html
# 原本想输出中文,乱码了,设置了 ENV LANG C.UTF-8 或者 ENV LANG zh_CN.UTF-8 都不行 放弃了,有知道大神望告知!
RUN echo 'hello,oKong' > /usr/share/nginx/html/index.html
# 启动命令 不写时 会直接使用基础镜像的启动命令
CMD ["nginx", "-g", "daemon off;"]
然后利用build
命令进行关键。
docker build -t lqdev.cn/mynginx:v1 .
注意:这里最后面有个(.)
,路径参数,而(.)
表示是当前路径。
控制台会显示具体每一个执行说明
[root@izbp16chpwsnff41nrjtfhz docker]# docker build -t lqdev.cn/mynginx:v1 .
Sending build context to Docker daemon 2.56kB
Step 1/6 : FROM nginx
---> c82521676580
Step 2/6 : LABEL author="作者:oKong"
---> Running in 81eb0dc40699
Removing intermediate container 81eb0dc40699
---> 4d2799492a09
Step 3/6 : LABEL version="版本:v0.1"
---> Running in e4e0d6097bae
Removing intermediate container e4e0d6097bae
---> d47eb89ae7b4
Step 4/6 : LABEL desc="说明:修改nginx首页提示"
---> Running in 36b1bffc8345
Removing intermediate container 36b1bffc8345
---> 3e9b63e69b0a
Step 5/6 : RUN echo 'hello,oKong' > /usr/share/nginx/html/index.html
---> Running in 1f04dafc3bf6
Removing intermediate container 1f04dafc3bf6
---> c9a649422c1d
Step 6/6 : CMD ["nginx", "-g", "daemon off;"]
---> Running in f6f41f072643
Removing intermediate container f6f41f072643
---> 11e7ca53febd
Successfully built 11e7ca53febd
Successfully tagged lqdev.cn/mynginx:v1
查看镜像列表,就能看见刚刚构建的镜像了:
[root@izbp16chpwsnff41nrjtfhz docker]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
lqdev.cn/mynginx v1 11e7ca53febd About a minute ago 109MB
nginx latest c82521676580 7 days ago 109MB
lqdev.cn/hello-world 1 2cb0d9787c4d 3 weeks ago 1.85kB
hello-world latest 2cb0d9787c4d 3 weeks ago 1.85kB
然后,我们运行下:
docker run -p 80:80 -d lqdev.cn/mynginx:v1
之后访问宿主服务地址:http://宿主IP, 即可看见修改后的首页了:
同时,利用inspect
命令,查看镜像元数据,就可以看见刚刚指定的值了。
docker inspect 11e7ca53febd
所以可以看出Dockerfile主要分为四个部分
基础镜像信息
、元数据信息
、镜像操作指令
、启动执行指令
。下一部分就主要讲解下关于Dockerfile
的命令说明。
Dockerfile命令说明
FROM 指定基础镜像
放在第一行,其格式为:
#语法:
FROM <image>
FROM <image>:<tag>
FROM <image>:<digest>
若想构建一个最小的镜像,不想基于其他任何镜像时。可直接
FROM scratch
LABEL 镜像元数据
可以设置镜像的任何元数据,格式为:
LABEL <key>=<value> <key>=<value> <key>=<value> ...
例如:
LABEL author="作者:oKong"
LABEL version="版本:v0.1"
LABEL desc="说明:修改nginx首页提示"
然后利用docker inspect
命令进行查看。
"Labels": {
"author": "作者:oKong",
"desc": "说明:修改nginx首页提示",
"maintainer": "NGINX Docker Maintainers <docker-maint@nginx.com>",
"version": "版本:v0.1"
},
ENV 设置环境变量
主要就是设置环境变量,之后的命令都可以用此变量进行赋值,格式如下:
ENV <key> <value>
ENV <key>=<value> ...
VOLUME 定义匿名卷
VOLUME用于创建挂载点,即向基于所构建镜像创始的容器添加卷:
VOLUME ["/data"]
一个卷可以存在于一个或多个容器的指定目录,该目录可以绕过联合文件系统,并具有以下功能:
- 卷可以容器间共享和重用
- 容器并不一定要和其它容器共享卷
- 修改卷后会立即生效
- 对卷的修改不会对镜像产生影响
- 卷会一直存在,直到没有任何容器在使用它
VOLUME
让我们可以将源代码、数据或其它内容添加到镜像中,而又不并提交到镜像中,并使我们可以多个容器间共享这些内容。
COPY 复制文件
主要就是构建镜像时,进行拷贝文件到镜像的指定路径下,格式为:
COPY <源路径>... <目标路径>
COPY ["<源路径1>",... "<目标路径>"]
ADD 更高级的复制文件
ADD
指令和 COPY
的格式和性质基本一致。但是在 COPY
基础上增加了一些功能。比如<源路径>
可以是一个 URL
,这种情况下,Docker
引擎会试图去下载这个链接的文件放到<目标路径>
去。
EXPOSE 设置监听端口
为镜像设置监听端口,容器运行时会监听改端口,格式为:
EXPOSE <port> [<port>/<protocol>...]
如,nginx
镜像,监听了80端口
EXPOSE 80
同时,也能指定协议名,如:
EXPOSE 80/udp
ARG 设置构建参数
该命令用于设置构建参数,该参数在容器运行时是获取不到的,只有在构建时才能获取。这也是其和ENV
的区别。
ARG <name>[=<default value>]
使用举例:
arg author=okong
# 构建时,也可以替换了
# docker build --build-arg <varname>=<value>
docker build --build-arg author=okong0123
RUN 执行命令
在镜像的构建过程中执行特定的命令,并生成一个中间镜像。格式:
RUN <command>
或者
RUN ["executable", "param1", "param2"]
这也是很常用的一个功能了。
第一种后边直接跟shell命令
- 在linux操作系统上默认 /bin/sh -c
- 在windows操作系统上默认 cmd /S /C
第二种是类似于函数调用。
可将executable
理解成为可执行文件,后面就是两个参数。
两种写法比对:
RUN /bin/bash -c 'source $HOME/.bashrc; echo $HOME
RUN ["/bin/bash", "-c", "echo hello"]
注意:多行命令不要写多个RUN
,原因是Dockerfile
中每一个指令都会建立一层.多少个RUN就构建了多少层镜像,会造成镜像的臃肿、多层,不仅仅增加了构件部署的时间,还容易出错。
RUN
书写时的换行符是\
CMD 启动时命令
功能为容器启动时要运行的命令,
语法有三种写法
1. CMD ["executable","param1","param2"]
2. CMD ["param1","param2"]
3. CMD command param1 param2
第三种比较好理解了,就时shell
这种执行方式和写法,第一种和第二种其实都是可执行文件加上参数的形式:
举例说明两种写法:
CMD [ "sh", "-c", "echo $HOME"
CMD [ "echo", "$HOME" ]
补充细节:这里边包括参数的一定要用双引号,就是双引号"
,不能是单引号。千万不能写成单引号
。原因是参数传递后,docker
解析的是一个JSON array
。
ENTRYPOINT 启动默认命令
ENTRYPOINT
用于给容器配置一个可执行程序。也就是说,每次使用镜像创建容器时,通过 ENTRYPOINT
指定的程序都会被设置为默认程序。ENTRYPOINT
有以下两种形式:
ENTRYPOINT ["executable", "param1", "param2"]
ENTRYPOINT command param1 param2
ENTRYPOINT
与 CMD
非常类似,不同的是通过docker run
执行的命令不会覆盖 ENTRYPOINT
,而docker run
命令中指定的任何参数,都会被当做参数再次传递给ENTRYPOINT
。Dockerfile
中只允许有一个 ENTRYPOINT
命令,多指定时会覆盖前面的设置,而只执行最后的 ENTRYPOINT
指令。
docker run
运行容器时指定的参数都会被传递给ENTRYPOINT
,且会覆盖 CMD 命令指定的参数。如,执行docker run <image> -d
时,-d
参数将被传递给入口点。
也可以通过docker run --entrypoint
重写 ENTRYPOINT
入口点。如:可以像下面这样指定一个容器执行程序:
ENTRYPOINT ["/usr/bin/nginx"]
这里以上面Dockerfile格式
章节,作为例子:
# 注意:第一行 必须以FROM 开头。
# FROM 指定基础镜像,即以此镜像作为基础
FROM nginx
# 设置元数据,利用 docker inspect [镜像名称|镜像ID],即可查看。
LABEL author="作者:oKong"
LABEL version="版本:v0.1"
LABEL desc="说明:修改nginx首页提示"
# 操作执行,这里直接修改了nginx的html的首页内容,/usr/share/nginx/html
# 原本想输出中文,乱码了,设置了 ENV LANG C.UTF-8 或者 ENV LANG zh_CN.UTF-8 都不行 放弃了,有知道大神望告知!
RUN echo 'hello,oKong' > /usr/share/nginx/html/index.html
# 启动命令 不写时 会直接使用基础镜像的启动命令
# CMD ["nginx", "-g", "daemon off;"]
# 这里利用 ENTRYPOINT 改写
ENTRYPOINT ["nginx"]
使用docker build
构建镜像,并将镜像指定为lqdev.cn/mynginx:v2
:
docker build -t lqdev.cn/mynginx:v2 .
构建完成后,使用lqdev.cn/mynginx:v2
启动一个容器:
docker run -p 80:80 -d lqdev.cn/mynginx:v2 -g "daemon off;"
在运行容器时,我们使用了 -g "daemon off;"
,这个参数将会被传递给 ENTRYPOINT
,最终在容器中执行的命令为 nginx -g "daemon off;"
。此时,可利用docker ps -a
查看下,最后效果是一样的。
WORKDIR 指定工作目录
用于在容器内设置一个工作目录:
WORKDIR /opt/docker/workdir
通过WORKDIR
设置工作目录后,Dockerfile
中其后的命令 RUN
、CMD
、ENTRYPOINT
、ADD
、COPY
等命令都会在该目录下执行。
USER 指定当前用户
用于指定运行镜像所使用的用户:
USER okong
使用USER
指定用户后,Dockerfile
中其后的命令RUN
、CMD
、ENTRYPOINT
都将使用该用户。镜像构建完成后,通过docker run
运行容器时,可以通过-u
参数来覆盖所指定的用户。
其他命令
还有像
ONBUILD
、STOPSIGNAL
、SHELL
及其MAINTAINER(已弃用)
等命令,不是十分常用或者已经弃用的,这里不阐述了。主要是没看懂具体啥意思,⊙﹏⊙‖∣。大家可通过其官网进行查看下:https://docs.docker.com/engine/reference/builder/
总结
本章节主要是介绍了下
Dockerfile
的一些常用命令的说明。学习掌握了Dockerfile
命令使用后,我们就能进行个性化镜像的构建了。本章节只是简单演示了下,下一章节,我们就主要来一步步动手构建一个属于自己的镜像文件!
最后
若文中有错误或者遗漏之处,还望指出,共同进步!
参考资料
- https://docs.docker.com/engine/reference/builder
- http://www.ityouknow.com/docker/2018/03/15/docker-dockerfile-command-introduction.html
- https://www.cnblogs.com/dazhoushuoceshi/p/7066041.html
老生常谈
- 个人QQ:
499452441
- 微信公众号:
lqdevOps
个人博客:http://blog.lqdev.cn
原文地址:http://blog.lqdev.cn/2018/08/02/docker/docker-four/
Docker | 第四章:Dockerfile简单介绍及使用的更多相关文章
- [Docker]学习笔记--简单介绍
学习docker已经有一段时间了,一直没有静下心来好好总结一下. 最近用docker搭了一整套Gitlab的持续集成环境.(会在下一篇中详细的讲解具体步骤,敬请期待) 感觉是时候写点东西和大家一起分享 ...
- 第四章 USB库介绍
4.1 USB库函数简介 Luminary Micro公司提供USB处理器的USB库函数,应用在Stellaris处理器上,为USB设备.USB主机.OTG开发提供USB协议框架和API函数,适用于多 ...
- docker(8)Dockerfile指令介绍
前言 Dockerfile 是一个用来构建镜像的文本文件,文本内容包含了一条条构建镜像所需的指令和说明. Dockerfile简介 Dockerfile是用来构建Docker镜像的构建文件,是由一系列 ...
- Docker(四)Dockerfile入门
摘自: https://mp.weixin.qq.com/s/Im4axroExgrJoj05g_TQ-w 一.Docker的工作流程 Docker组件协作运行容器可以分为以下几个过程: Docker ...
- 四:多线程--NSOperation简单介绍
一.NSOperation简介 1.NSOperation的作⽤:配合使用NSOperation和NSOperationQueue也能实现多线程编程 NSOperation和NSOperationQu ...
- Docker | 第零章:前言
说在前面 对于一个后端开发者而言,对于Docker也是前年十月份才开始听说的(很惭愧,Docker在2013年就已经出现了).当时有个新项目启动,领导们在技术选型时,在部署方面选定的是Docker.那 ...
- PHP 17: MySQL的简单介绍
原文:PHP 17: MySQL的简单介绍 这一章将简单介绍MySQL的基本知识. 本文来自http://lib.hackbase.com/html/8/35125.htm. MySQL是最受欢迎的开 ...
- 《Java从入门到失业》第四章:类和对象(4.1):初识类和对象
4类和对象 在第一章曾经简单介绍过,在面向对象的世界里,一切事物皆对象,当解决一个问题的时候,我们先会考虑这个问题会涉及到哪些事物,然后把事物抽象成类,当时还画了一张图如下: 从本章开始,我们一点一点 ...
- Docker(二):Dockerfile 使用介绍
上一篇文章Docker(一):Docker入门教程介绍了 Docker 基本概念,其中镜像.容器和 Dockerfile .我们使用 Dockerfile 定义镜像,依赖镜像来运行容器,因此 Dock ...
随机推荐
- js---复选框(全选,不选,反选)demo1--
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/stri ...
- python unittest之断言及示例
python unintest单元测试框架提供了一整套内置的断言方法. 如果断言失败,则抛出一个AssertionError,并标识该测试为失败状态 如果异常,则当做错误来处理 注意:以上两种方式的区 ...
- mybatis 学习二 conf xml 配置信息
xml映射配置文件 这个xml文件主要包括一下节点信息 * properties 属性 * settings 设置 * typeAliases 类型命名 ...
- C语言学习笔记--enum和sizeof关键字
1.enum关键字 C语言中enum关键字用来定义枚举类型 (1)enum 是 C 语言中的一种自定义类型(2)enum 值是可以根据需要自定义的的整型值(3)第一个定义的 enum 值默认为 0 ( ...
- 关于使用struts2跳转后css和js失效的解决方式
根据观察,主要是由于通过action跳转后的url会根据命名空间,自动跳转到命名空间子目录,使得当前引用的css和js查找不到,从而失效,根据这个原因,可使用四种办法解决: 1.使用struts2.x ...
- Java探索之旅(2)——GUI输入输出与代码的规范性
1.知识点概叙 ① 定名常量:关键字final,类似C++ const定义,一般用大写:final double PI=3.1415926 ② 5/2=2:5.0/2=2.5://通常意义的除法,至少 ...
- mysql nginx redis 配置文件
https://github.com/superhj1987/awesome-config
- 自签名配置HTTPS
基于AFN3.0 1.将后台提供的.cer文件文件保存至本地 2.在封装的网络请求工具类中为AFN的AFSecurityPolicy属性赋值 -(AFSecurityPolicy *)customSe ...
- 浅析C#中的事件
讲过了委托,不得不讲事件. 事件基于委托,为委托提供了一种发布/订阅机制. 在发生其他类或对象关注的事情时,类或对象可通过事件通知它们.发送(或引发)事件的类称为“发行者”,接收(或处理)事件的类称为 ...
- 使用 typescript ,提升 vue 项目的开发体验(2)
此文已由作者张汉锐授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. vuex-class 提供了和 vuex 相关的全部装饰器,从而解决了上面 Vue.extend + vue ...