Docker Dockerfile 文件指令

Docker Dockerfile 文件指令

Dockerfile 指令

指令有很多,这里对一些比较常用的指令进行描述,更具体的可以阅读官方的 Dockerfile 文档

##FROM 功能为指定基础镜像,并且必须是第一条指令

不指定基础 Image:scratch

FROM <image>
FROM <image>:<tag>
FROM <image>:<digest>

最佳实践:尽量使用官方的 Base image

LABEL

定义作者信息,或者 dockerfile 文件的描述。

LABEL <NAME>=<CONTENT>

LABEL maintainer="szlwl01@qq.com"
LABEL version="xxx"
LABEL descripton="this is descripton"

最佳实践:最好每个 dockerfile 都要都这些描述信息

RUN

在容器里面运行的命令

RUN <SHELL>

RUN yum update && yum install -y vim \
    mysql

RUN /bin/bash -c 'source $HOME/.bashrc; echo $HOME'

最佳实践:命令过长使用反斜杠换行,并且因为每一条指令都会创建一层,所以尽量使用 && 合并成一个 RUN 指令

WORKDIR

设置容器的当前工作目录

若是设置的目录不存在,则会自动创建。多个 WORKDIR 指令会合并成一条。

WORKDIR <WORKDIR_PATH>

WORKDIR /app

上面的指令作用类是于:mkdir /app && cd app

最佳实践:不要使用 RUN cd 来单纯的切换目录,使用绝对路径。

ADD

将本地文件添加到容器中,也可以是远程文件

此指令在添加压缩文件的时候会自动解压缩。

ADD <LOCAL_PATH> <CONTAINER_PATH>

ADD test.tar /

最佳实践:若是有远程文件或者压缩文件,使用该指令

COPY

将本地文件复制到容器中

此指令在添加压缩文件的时候会自动解压缩。

COPY <LOCAL_PATH> <CONTAINER_PATH>

COPY test.html /

最佳实践:一般情况会优先使用该指令移动文件

ENV

设置环境变量

ENV <NAME> <VALUE>

ENV MYSQL_VERSION 5.7

使用变量:${MYSQL_VERSION}

最佳实践:频繁使用,并且以后可能修改的某个值,尽可能定义成变量,增加可维护性。

VAOLUME

存储

EXPOSE

网络

CMD

容器启动后默认值执行的命令和参数

支持两种格式:Shell 和 Exec 格式


// Shell
CMD echo "hello world!"

//Exec
CMD ["/bin/bash", "-c", "echo hello world!"]

多个 CMD,只执行最后一个 CMD,可以被 docker run 时指定的命令覆盖


CMD ["/bin/bash", "-c", "echo hello world!"]

CMD ["/bin/bash", "-c", "echo hello docker!"]

只会执行后面一个 CMD 指令。

docker run 覆盖 Dockerfile 文件的 CMD 指令

docker run -it [image] /bin/bash

最佳实践:没有

ENTRYPOINT

设置容器启动时运行的命令

与 CMD 不同,该指令让容器以应用程序或者服务的形式运行,并且一定会执行。

支持两种格式:Shell 和 Exec 格式

// Shell
ENTRYPOINT echo "hello world!"

//Exec
ENTRYPOINT ["/bin/bash", "-c", "echo hello world!"]

最佳实践:写一个 shell 脚本来作为 ENTRYPOINT

ENTRYPONT ["docker-entrypoint.sh"]

例子

该例子是一个 Docker 官方的 Golang Dockerfile 文件,它的作用是构建一个 Golang 的 Image 镜像

它使用的 Base Image 也是 Docker 官方提供的,一个小巧的 Linux 镜像:alpine

FROM alpine:3.9

RUN apk add --no-cache \
		ca-certificates

# set up nsswitch.conf for Go's "netgo" implementation
# - https://github.com/golang/go/blob/go1.9.1/src/net/conf.go#L194-L275
# - docker run --rm debian:stretch grep '^hosts:' /etc/nsswitch.conf
RUN [ ! -e /etc/nsswitch.conf ] && echo 'hosts: files dns' > /etc/nsswitch.conf

ENV GOLANG_VERSION 1.12.4

RUN set -eux; \
	apk add --no-cache --virtual .build-deps \
		bash \
		gcc \
		musl-dev \
		openssl \
		go \
	; \
	export \
# set GOROOT_BOOTSTRAP such that we can actually build Go
		GOROOT_BOOTSTRAP="$(go env GOROOT)" \
# ... and set "cross-building" related vars to the installed system's values so that we create a build targeting the proper arch
# (for example, if our build host is GOARCH=amd64, but our build env/image is GOARCH=386, our build needs GOARCH=386)
		GOOS="$(go env GOOS)" \
		GOARCH="$(go env GOARCH)" \
		GOHOSTOS="$(go env GOHOSTOS)" \
		GOHOSTARCH="$(go env GOHOSTARCH)" \
	; \
# also explicitly set GO386 and GOARM if appropriate
# https://github.com/docker-library/golang/issues/184
	apkArch="$(apk --print-arch)"; \
	case "$apkArch" in \
		armhf) export GOARM='6' ;; \
		x86) export GO386='387' ;; \
	esac; \
	\
	wget -O go.tgz "https://golang.org/dl/go$GOLANG_VERSION.src.tar.gz"; \
	echo '4affc3e610cd8182c47abbc5b0c0e4e3c6a2b945b55aaa2ba952964ad9df1467 *go.tgz' | sha256sum -c -; \
	tar -C /usr/local -xzf go.tgz; \
	rm go.tgz; \
	\
	cd /usr/local/go/src; \
	./make.bash; \
	\
	rm -rf \
# https://github.com/golang/go/blob/0b30cf534a03618162d3015c8705dd2231e34703/src/cmd/dist/buildtool.go#L121-L125
		/usr/local/go/pkg/bootstrap \
# https://golang.org/cl/82095
# https://github.com/golang/build/blob/e3fe1605c30f6a3fd136b561569933312ede8782/cmd/release/releaselet.go#L56
		/usr/local/go/pkg/obj \
	; \
	apk del .build-deps; \
	\
	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