Dockerfile 的常用命令
⚫ FROM:继承基础镜像
⚫ MAINTAINER:镜像制作作者的信息,已弃用,使用LABEL替代
⚫ LABEL:k=v形式,将一些元数据添加至镜像
⚫ RUN:用来执行shell命令
⚫ EXPOSE:暴露端口号
⚫ CMD:启动容器默认执行的命令,会被bash覆盖
⚫ ENTRYPOINT:启动容器真正执行的命令,不会被bash覆盖
⚫ ENV:配置环境变量
⚫ ADD:复制文件到容器,压缩包自动解压
⚫ COPY:复制文件到容器
⚫ WORKDIR:设置进入容器时默认进入的的工作目录
⚫ USER:进入容器时默认使用的用户
⚫ ARG:设置编译镜像时传入的参数
注:使用COPY或ADD命令时,带复制的文件需要与Dockerfile
CMD 和 ENTRYPOINT 区别
cat Dockerfile
# base image
FROM centos:7
MAINTAINER dot
RUN useradd dot
RUN mkdir dot
ENV envir=test version=1.0
#CMD echo "envir:$envir version:$version"
ENTRYPOINT echo "envir:$envir version:$version"
执行构建并测试:
docker build -t centos:entrypoint .
docker run --rm centos:entrypoint
envir:test version:1.0
CMD 可以被覆盖:
docker run --rm centos:env-cmd echo "cover..."
cover...
ENTRYPOINT 指定的不能被直接覆盖:
docker run --rm centos:entrypoint echo "cover..."
envir:test version:1.0
ENTRYPOINT 指定–entrypoint 参数,比如指定 entrypoint 为 ls,后置命令为/tmp,就相当于
ENTRYPOINT 是 ls,CMD 是/tmp
就是当entrypoint与cmd同时出现时,cmd会被当做entrypoint的参数
docker run --rm --entrypoint=ls centos:entrypoint /tmp
anaconda-post.log
yum.log
dockerfile动态传参
使用 ARG 和 build-arg 传入动态变量:
# base image
FROM centos:7
# MAINTAINER dot # deprecated
LABEL maintainer="dot" version="demo"
LABEL multiple="true"
ARG USERNAME
ARG DIR="defaultValue"
RUN useradd -m $USERNAME -u 1001 && mkdir $DIR
docker build --build-arg USERNAME="test_arg" -t test:arg .
docker run -ti --rm test:arg bash
[root@fe7a40927736 /]# ls
bin dev home lib64 media opt root selinux sys usr
defaultValue etc lib lost+found mnt proc sbin srv tmp var
[root@fe7a40927736 /]# tail -1 /etc/passwd
test_arg:x:1001:1001::/home/test_arg:/bin/bash
镜像大小优化
选择合适基础镜像
使用 Alpine 作为基础镜像
将之前创建用户的 Dockerfile 改为 Alpine 镜像
# cat Dockerfile
# base image
# FROM centos:7
FROM alpine:3.12
MAINTAINER dot
RUN adduser -D dot
Alpine 镜像创建用户的命令为 adduser,-D 表示不设置密码
执行构建并查看镜像大小:
# docker build -t alpine:user .
...
Successfully built 262f8225d7ec
...
# docker images | grep 262f8225d7ec
alpine user 262f8225d7ec 4 minutes ago
5.57MB
镜像多阶段构建
创建 Go 语言 Hello World 程序:
# cat hw.go
package main
import "fmt"
func main() {
fmt.Println("Hello World!")
}
单阶段构建:
# build step
FROM golang:1.14.4-alpine
WORKDIR /opt
COPY hw.go /opt
RUN go build /opt/hw.go
CMD "./hw"
执行构建并运行测试:
docker build -t hw:one .
Successfully built e036098fbb2e
Successfully tagged hw:one
docker run --rm hw:one
Hello World!
查看此时由一个阶段构建的镜像大小:
docker images | grep e036098fbb2e
hw one e036098fbb2e 5 minutes ago
372MB
可以看到此时镜像大小为 372MB,但是上述的代码我们只需要构建步骤产生的二进制文件
hw 即可,这个文件大小可以进入到容器内部看一下:
docker run --rm hw:one du -sh ./hw
2.0M ./hw
多阶段 Dockerfile 构建:
cat Dockerfile
# 构建过程
FROM golang:1.14.4-alpine as builder
WORKDIR /opt
COPY hw.go /opt
RUN go build /opt/hw.go
# CMD "./hw"
# 生成应用镜像过程
FROM alpine:3.12
COPY --from=builder /opt/hw .
CMD [ "./hw" ]
再次构建后查看此时的镜像大小和运行镜像的效果:
docker build -t hw:multi .
docker images |grep multi
hw multi a3bba8204f75 6 minutes ago 2.07MB
docker run --rm hw:multi
Hello World!