docker(三、dockerfile)
- 概述:dockerfile是一个用来构建镜像的文件。
- 在实际工作中,构建镜像的基本步骤
- 编写Dockerfile
- 通过Dockerfile构建镜像
- 通过镜像产生容器
- dockerfile书写规则
- (#)表示注释
- 每个指令都是大写字母
- 指令是按照从上到下的顺序执行的
- docker执行dockerfile的流程
- docker从基础镜像运行一个容器
- 执行一条指令并对容器进行修改
- 执行类似于
docker commit
的操作提交一个新的镜像层 - docker在基于刚提交的下一条指令运行一个新的容器
- 直到所有指令执行完成
- docker hub中golang的Dockerfile
FROM buildpack-deps:stretch-scm
# gcc for cgo
// 配置golang所需的开发环境,这条命令需要较长的时间
RUN apt-get update && apt-get install -y --no-install-recommends \
g++ \
gcc \
libc6-dev \
make \
pkg-config \
&& rm -rf /var/lib/apt/lists/*
ENV GOLANG_VERSION 1.12.5
RUN set -eux; \
\
# this "case" statement is generated via "update.sh"
dpkgArch="$(dpkg --print-architecture)"; \
case "${dpkgArch##*-}" in \
amd64) goRelArch='linux-amd64'; goRelSha256='aea86e3c73495f205929cfebba0d63f1382c8ac59be081b6351681415f4063cf' ;; \
armhf) goRelArch='linux-armv6l'; goRelSha256='311f5e76c7cec1ec752474a61d837e474b8e750b8e3eed267911ab57c0e5da9a' ;; \
arm64) goRelArch='linux-arm64'; goRelSha256='ff09f34935cd189a4912f3f308ec83e4683c309304144eae9cf60ebc552e7cd8' ;; \
i386) goRelArch='linux-386'; goRelSha256='146605e13bf337ff3aacd941a816c5d97a8fef8b5817e07fcec4540632085980' ;; \
ppc64el) goRelArch='linux-ppc64le'; goRelSha256='e88b2a2098bc79ad33912d1d27bc3282a7f3231b6f4672f306465bf46ff784ca' ;; \
s390x) goRelArch='linux-s390x'; goRelSha256='168d297ec910cb446d1aea878baeb85f1387209f9eb55dde68bddcd4c006dcbb' ;; \
*) goRelArch='src'; goRelSha256='2aa5f088cbb332e73fc3def546800616b38d3bfe6b8713b8a6404060f22503e8'; \
echo >&2; echo >&2 "warning: current architecture ($dpkgArch) does not have a corresponding Go binary release; will be building from source"; echo >&2 ;; \
esac; \
\
url="https://golang.org/dl/go${GOLANG_VERSION}.${goRelArch}.tar.gz"; \
wget -O go.tgz "$url"; \
echo "${goRelSha256} *go.tgz" | sha256sum -c -; \
tar -C /usr/local -xzf go.tgz; \
rm go.tgz; \
\
if [ "$goRelArch" = 'src' ]; then \
echo >&2; \
echo >&2 'error: UNIMPLEMENTED'; \
echo >&2 'TODO install golang-any from jessie-backports for GOROOT_BOOTSTRAP (and uninstall after build)'; \
echo >&2; \
exit 1; \
fi; \
\
export PATH="/usr/local/go/bin:$PATH"; \
go version
ENV GOPATH /go
ENV PATH $GOPATH/bin:/usr/local/go/bin:$PATH
RUN mkdir -p "$GOPATH/src" "$GOPATH/bin" && chmod -R 777 "$GOPATH"
WORKDIR $GOPATH
Dockerfile指令说明
- Dockerfile指令一般被分为两种:配置指令与操作指令
- 配置指令
ARG 定义创建过程中使用的变量
FROM 指定所创建镜像的基础镜像
LABEL 为生成的镜像添加元数据
EXPOSE 声明镜像内的服务监听的端口
ENV 指定环境变量
ENTRYPOINT 镜像的默认入口命令
VOLUME 创建一个数据卷
USER 指定运行容器时的用户名或UID
WORKDIR 配置工作目录
ONBUILD 创建子镜像的时候,自动执行的一些操作指令
SHELL 默认的shell类型
- 操作指令
RUN 运行指定命令
CMD 启动容器时默认执行的命令
ADD 添加文件/数据到镜像中
COPY 复制文件/数据到镜像中
docker build通过dockerfile创建镜像的基本步骤
- 查找dockerfile
- 查找当前路径以及上当路径的子目录
- 如果没有可以通过-f进行指定
- 将该路径下所有数据作为上下文发送给docker服务端
- 服务端校验Dockerfile
- 逐条执行Dockerfile中的指令
- 在执行指令的过程中,碰到ADD、COPY、RUN指令会生成一层新的镜像
- 返回最终镜像的生成ID
常用命令:
Usage: docker build [OPTIONS] PATH | URL | -
Build an image from a Dockerfile
Options:
--add-host list 添加自定义的主机名到IP的映射
--build-arg list 添加创建时的变量
--compress 使用gzip来压缩创建上下文数据
-f, --file string 指定Dockerfile名称
--force-rm 删除中间过程的容器
--iidfile string 将镜像ID写入文件
--isolation string 容器的隔离机制
--label list Set metadata for an image
--pull 总是深度获取镜像的最新版本
-q, --quiet 不打印创建过程中的日志信息
--rm 创建成功后自动删除中间过程的容器
-t, --tag list 指定镜像的标签
进一步了解:
- docker 在运行时分为
Docker引擎(服务端的守护进程)
,以及客户端工具
,我们在日常使用docker各种命令实际上是在用docker客户端与引擎进行交互。 - 所以在使用docker build来构建镜像时,构建镜像的过程是在docker引擎中完成的,而不是在本机环境完成的
docker build .
的.
号指的是在镜像构建过程中的上下文环境的目录- 在创建dockerfile过程中,需要注意的问题:不要在Dockerfile路径下放无关数据,因为docker会将该路径下所有数据作为上下文发送给docker服务端,如果该路径太大,影响构建效率
构建镜像
- 选择父镜像:父镜像是要生成的镜像的基础,会直接影响到生成的镜像的大小和功能
在Dockerfile中,通过FROM指定父镜像:
FROM scratch
# scratch表示空镜像
ADD hello / # 把一个hello可执行文件添加到容器根目录下
CMD ["/hello"] # 执行命令
- 编写golang测试代码
// hello
package main
import "fmt"
func main(){
fmt.Printf("hello")
}
- 编译hello.go,生成hello可执行文件
go build -o hello hello.go
- 构建镜像:
docker build -t hello-tencent .
,命名为hello-tencent,标签默认为latest,指定当前目录为上下文路径(将当前目录的所有文件打包到docker服务器) - 运行docker:
docker run -it hello-tencent
,输出hello - 使用
.dockerignore
文件:
在docker build
的过程中,指定的上下文目录中不是所有文件都会在Dockerfile
文件中使用到,此时就可以指定在传递给docker 引擎
时需要忽略掉的文件或文件夹
多步骤创建
- 对于需要编译的应用的来说,一般至少要两个环境的docker的docker镜像
- 编译环境镜像:包括完整的编译引擎、依赖库,往往会比较庞大,主要是编译应用为二进制文件
- 运行环境镜像:复用编译好的二进制文件,运行应用,不需要编译环境,体积比较少
- 可以通过多步骤创建,实现单一的Dockerfile,降低维护复杂度
之前是在centos中编译后,在docker中运行,现在将编译工作也转移到docker中:
- 步骤:
- 编写golang代码
// hello
package main
import "fmt"
func main(){
fmt.Printf("hello")
}
- 编写dockerfile
## 步骤一
FROM golang:1.8 as builder # 好几百M,可能会出现retrying
## 创建一个测试目录
RUN mkdir -p /go/src/test
## 配置工作目录
WORKDIR /go/src/test
## 将main.go拷贝到工作目录下
COPY main.go .
## 系统配置,生成应用程序
RUN CGO_ENABLE=0 GOOS=linux go build -o app .
## 步骤二
FROM alpine:latest
WORKDIR /root/
# 将前面获取到的go环境拷贝过来,才能运行app应用程序
COPY --from=builder /go/src/test/app .
CMD["./app"]
构建镜像:docker build -t test-mul-go:latest .
运行docker:docker run -it test-mul-go
,输出hello
tomcat实战