Docker学习笔记(三):Dockerfile及多步骤构建镜像
Dockerfile指令
官方文档地址:https://docs.docker.com/engine/reference/builder/
Dockerfile是一个文本格式的配置文件,其内容包含众多指令,用户可以使用它快速的创建自定义镜像。
部分指令列表
指令 | 作用 | 备注 |
---|---|---|
FROM | 指定基础镜像 | 任何Dockerfile中的第一条指令都必须是FROM 一个文件中可以存在多个FROM指令。 |
LABEL | 为镜像添加元数据标签信息。 | |
ARG | 定义创建镜像过程中使用的变量,编译成功后不存在。 | 在运行docker build时,指定--builder-arg为变量赋值。 |
ENV | 设置环境变量 | 在镜像启动时也会存在。 docker run --env key=value 会覆盖同名变量 |
WORKDIR | 指定工作目录 | 可以使用多个,建议使用绝对路径。 |
VOLUME | 创建数据卷挂载点 | 例如VOLUME ["/data/a","/data/b"] |
EXPOSE | 声明镜像内服务监听的端口 | 只起声明作用,不会自动完成映射。 |
USER | 指定运行容器时的用户名或ID | 后续RUN指令也会以这个用户身份运行。 |
STOPSIGNAL | 指定所创建镜像启动的容器接收退出的信号值 |
COPY/ADD
COPY src dst / ADD src dst
其相同点是:作用都是复制内容到镜像中;dst不存在时会创建;路径支持正则。
不同点在于:
- ADD的src可以是相对于Dockerfile的相对路径;也可以是一个URL;还可以是一个tar文件(自动解压)。
- COPY的src只能是文件或者目录。
除了目的明确是要将一个URL或者tar文件作为src的情况下,其他情况推荐使用COPY。
CMD/ENTRYPOINT
命令格式
- exec方式: ["executable","param1","param2"](JSON数组,所以一定要是双引号)
- shell方式: command param1 param2
CMD与ENTRYPOINT两种方式都支持,但推荐使用exec方式。
作用
在任意一个Dockerfile下:
- 只有最后一条CMD才会被执行。用来指定容器启动时默认执行的命令及参数。但是会被docker run命令行参数覆盖。
- 只有最后一条ENTRYPOINT才会被执行。用来配置容器启动时的执行命令。并且会将docker run的命令行参数或者CMD的所有参数追加在ENTRYPOINT指令后作为参数。运行时可以被--entrypoint参数覆盖。
伪代码
finallyCommand = ""
if exists(ENTRYPOINT) {
finallyCommand = ENTRYPOINT
if exists(dockerRunCommandParam){
// 情景一
finallyCommand += dockerRunCommandParam
}elseif exists(CMD) {
// 情景二。除了CMD指令本身,包括后面JSON数组所有
finallyCommand += CMDParams
}
// 情景三
}elseif exists(dockerRunCommandParam){
// 情景四
finallyCommand = dockerRunCommandParams
}elseif exists(CMD){
// 情景五
finallyCommand = CMD
}
总结起来一句话:有ENTRYPOINT,CMD和docker run指定的命令都作为参数追加到ENTRYPOINT的参数后;没有ENTRYPOINT,docker run指定了命令就执行,否则执行CMD(如果有的话)。
实操
Dockerfile内容、构建镜像
FROM alpine:latest
ENTRYPOINT ["/bin/echo","entrypoint"]
-> [feifei@ffmac.local] [~/work/docker] docker build -t test .
// 情景三
-> [feifei@ffmac.local] [~/work/docker] docker run --rm test
entrypoint
// 情景一
-> [feifei@ffmac.local] [~/work/docker] docker run --rm test 12 34
entrypoint 12 34
Dockerfile添加CMD指令、构建镜像
FROM alpine:latest
ENTRYPOINT ["/bin/echo","entrypoint"]
CMD ["/bin/echo","cmd"]
-> [feifei@ffmac.local] [~/work/docker] docker build -t test .
// 情景二:CMD中的 "/bin/echo" 没有被当做命令执行,而是与"cmd"一起成为了ENTRYPOINT的参数。
-> [feifei@ffmac.local] [~/work/docker] docker run --rm test
entrypoint /bin/echo cmd
Dockerfile删除ENTRYPOINT指令、构建镜像
FROM alpine:latest
CMD ["/bin/echo","cmd"]
-> [feifei@ffmac.local] [~/work/docker] docker build -t test .
// 情景五
-> [feifei@ffmac.local] [~/work/docker] docker run --rm test
cmd
// 情景四
-> [feifei@ffmac.local] [~/work/docker] docker run --rm test echo 33
33
RUN
exec方式:RUN ["executable","param1","param2"]
shell方式:RUN command param1 param2
每条RUN指令将在当前镜像基础上执行指令,并且提交为新的镜像层。当命令较长时可以使用\来换行
ONBUILD
ONBUILD [INSTRUCTION]
作为父镜像被使用时自动执行的命令。对孙子镜像无效。可用于自动编译,检查等。
假如父镜像ParentImage的Dockerfile中有如下指令:
ONBUILD RUN mkdir /root/test
使用docker build基于ParentImage创建子镜像ChildImage的时候,会先执行ParentImage中的ONBUILD指令。等价于在ChildImage中添加了:
RUN mkdir /root/test
HEALTHCHECK
健康检查
HEALTHCHECK [OPTIONS] CMD command :根据执行命令返回值判断,0是成功,1是不健康。
HEALTHCHECK NONE :禁止健康检查
OPTIONS参数如下:
- --interval=DURATION (default: 30s) 多长时间检查一次
- --timeout=DURATION (default: 30s) 检查一次的超时时间
- --start-period=DURATION (default: 0s) 开始阶段时长,此阶段内第一次成功之前的失败不计入retries。
- --retries=N (default: 3) 确定最终失败的重试次数
构建镜像
docker build
docker build [OPTIONS] PATH | URL | -
该命令默认读取指定路径下的Dockerfile(也可使用 -f 指定),并将该路径下的所有数据作为上下文发送给Docker服务端。逐条执行指令,生成镜像。
选择父镜像
一般情况下都需要使用FROM来指定父镜像,所以父镜像会影响到新生成镜像的大小和功能。
通常有两种镜像可作为父镜像:基础镜像和普通镜像(由第三方创建,基于基础镜像)。基础镜像一般是基于scratch或者Dockerfile中不存在FROM指令。
多步骤构建
对于编译型语言通常需要编译环境和运行环境两个镜像:
- 编译环境镜像:包括完整的编译环境、依赖库等,体积较大。作用是将代码编译为二进制程序。
- 运行环境镜像:运行二进制程序,而不需要与编译环境,体积比较小。
app.go
package main
import "fmt"
func main() {
fmt.Println("Hello World")
}
Dockerfile中使用两次FROM
FROM golang:1.14-alpine as builder
WORKDIR /go/src/test
COPY app.go .
RUN CGO_ENABLED=0 GOOS=linux go build -o app app.go
FROM alpine:latest
COPY --from=builder /go/src/test/app /root/ #此处 --from=builder 也可以改为 --from=0
CMD ["/root/app"]
构建、运行
-> [feifei@ffmac.local] [~/work/docker] docker build -t hello .
-> [feifei@ffmac.local] [~/work/docker] docker run --rm hello
Hello World
小技巧
清理untagged镜像
多阶段构建会生成编译环境镜像,也会将之前的同名镜像变为<none>:<none>
,清理此类镜像可执行以下命令:
docker rmi $(docker images --filter dangling=true -q)
COPY --from指定其他镜像
COPY指令的--from选项也可以指定本地或者远程仓库的镜像
准备一个Dockerfile,内容是从ubuntu镜像中COPY一个文件到新镜像的/root/下
FROM alpine:latest
COPY --from=ubuntu:latest /bin/bash /root/
CMD ["/bin/ls","/root/"]
dokcer build 构建镜像
-> [feifei@ffmac.local] [~/work/docker] docker build -t test .
Sending build context to Docker daemon 19.46kB
Step 1/3 : FROM alpine:latest
---> f70734b6a266
Step 2/3 : COPY --from=ubuntu:latest /bin/bash /root/
latest: Pulling from library/ubuntu
d51af753c3d3: Pull complete
fc878cd0a91c: Pull complete
6154df8ff988: Pull complete
fee5db0ff82f: Pull complete
Digest: sha256:747d2dbbaaee995098c9792d99bd333c6783ce56150d1b11e333bbceed5c54d7
Status: Downloaded newer image for ubuntu:latest
---> Using cache
---> 082f95ffaa69
Step 3/3 : CMD ["/bin/ls","/root/"]
---> Using cache
---> 76fa9d9a1abd
Successfully built 76fa9d9a1abd
Successfully tagged test:latest
dokcer run 运行镜像
-> [feifei@ffmac.local] [~/work/docker] docker run --rm test
bash
注意事项
- 使用
.dockerignore
文件,避免发送不必要的数据 - 提供注释和维护者信息
- 正确使用镜像版本号
- 每条RUN都会提交为新的镜像层,尽量合并RUN指令
- 删除缓存和临时文件
Docker学习笔记(三):Dockerfile及多步骤构建镜像的更多相关文章
- Docker学习笔记三 Dockerfile 指令 定制镜像
本文地址:https://www.cnblogs.com/veinyin/p/10412079.html 镜像是分层存储的,每一层都是独立存在的,修改当前层并不会修改其依赖的上一层,删除某一层也只是 ...
- Docker学习笔记三:Docker部署Java web系统
Docker部署Java Web系统 1.在root目录下创建一个路径test/app mkdir test && cd test&& mkdir app && ...
- Docker学习笔记之Dockerfile
Dockerfile的编写格式为<命令><形式参数>,命令不区分大小写,但一般使用大写字母.Docker会依据Dockerfile文件中编写的命令顺序依次执行命令.Docker ...
- Docker学习笔记三
4.Docker数据管理 4.1.数据卷 数据卷是一个可供容器使用的特殊目录,它将主机操作系统目录直接映射进容器,类似与Linux的mount行为. 特性: 数据卷可以在容器之间共事和重用,容器间传递 ...
- docker学习笔记5:利用commit命令创建镜像 和 删除本地镜像
一.概述 创建镜像有两种方法,一是用commit命令,二是用dockerfile方法(这个更常用,在下面文章介绍).本章介绍commit方法. 在介绍commit命令前,我们先回顾下对代码的版本控制, ...
- Docker学习(三): Dockerfile指令介绍
特别声明: 博文主要是学习过程中的知识整理,以便之后的查阅回顾.部分内容来源于网络(如有摘录未标注请指出).内容如有差错,也欢迎指正! =============系列文章============= 1 ...
- Docker学习笔记之二,基于Dockerfile搭建JAVA Tomcat运行环境
前言 在第一篇文字中,我们完全人工方式,一个命令一个命令输入,实现一个 java tomcat运行环境,虽然也初见成效,但很累人.如果依靠依靠脚本构建一个Tomcat容器实例,一个命令可以搞定,何乐而 ...
- Docker学习笔记总结
Docker学习笔记 https://yeasy.gitbooks.io/docker_practice/content/ 一 环境搭建 Ubuntu安装 .添加软件源的GPG密钥 curl -f ...
- Docker学习笔记之-在CentOS中安装Docker
上一节演示了如何 通过Xshell连接CentOS服务,链接:Docker学习笔记之-通过Xshell连接 CentOS服务 本节将演示 如何在CentOS中安装 Docker 第一步:更新系统包到最 ...
随机推荐
- linux上Docker安装gogs私服
一.背景介绍 Gogs 是一款类似GitHub的开源文件/代码管理系统(基于Git),Gogs 的目标是打造一个最简单.最快速和最轻松的方式搭建自助 Git 服务.使用 Go 语言开发使得 Gogs ...
- 关于log4j、jul、jcl、slf4j等等日志组件的理解
日志组件: 我们经常在开发项目的时候,需要打印记录项目过程中的一些日志.那我们经常大概会用到 log4j.jul.jcl.slf4j.simple.nop.logback 等等,那我们就详细介绍下这些 ...
- Android | 教你如何快速集成机器学习能力
背景 继上篇博文说了如何快速集成扫码以后 我又上官网去了解了一下其他的功能,其中机器学习服务是当下比较火的,而且还是免费的.就赶紧点进去学习一下.看看能够快速实现哪些功能. 链接在这里:https ...
- Python(5)
把 aaabbcccd 这种形式的字符串压缩成 a3b2c3d1 这种形式. print(''.join({i+str(s.count(i)) for i in s})) dic={} for i i ...
- Springboot以Jetty为容器实现http重定向到https
1 简介 之前讲解的Springboot整合https用的是tomcat作为容器,tomcat也是一个流行多年的老牌Java容器了.但针对不同的场景,还是会有不同的选择,如Jetty.Jetty是架构 ...
- 配置IIS5.5/6.0 支持 Silverlight
在安装完Silverlight1.1 Alpha后,要使自己的IIS服务器支持Silverlight的浏览还需要配置一下IIS网站的 Http头->MIME映射添加内容如下:扩展名 ...
- 阿里大牛带你深入分析spring事务传播行为
spring框架封装了很多有用的功能和组件,便于在项目开发中快速高效的调用,其中spring的事务使用非常简单,只需要在用到事务的地方加一行注解即可: 1@Transactional 但越是看起来简单 ...
- Omnicore RPC API中文文档
2019独角兽企业重金招聘Python工程师标准>>> OmniCore是比特币核心的一个分支,它在比特币协议之上实现了一个新的Omni协议层,用于代币发行.众售等应用,USDT就是 ...
- web前端项目中遇到的一些问题总结(08.23更新)
个人网站 https://iiter.cn 程序员导航站 开业啦,欢迎各位观众姥爷赏脸参观,如有意见或建议希望能够不吝赐教! 写一些最近工作中Vue项目中遇到的问题. 巴啦啦小魔仙,污卡拉,全身变,小 ...
- log4j MDC NDC详解
NDC ( Nested Diagnostic Context )和 MDC ( Mapped Diagnostic Context )是 log4j 种非常有用的两个类,它们用于存储应用程序的上下文 ...