1. docker -f dockerfile1 -t 镜像名:tag .
  2. -f指定dockerfile 文件
  3. . 当前目录

其中镜像名可以是name1/name2:tag 注意容易写成路径形式/name1/name2:tag 会报错
docker build 的时候可以明显看出层结构,dockerfile 中的每一个命令就是一层

语法

FROM

定制的镜像都是基于 FROM 的镜像,这里的 nginx 就是定制需要的基础镜像。后续的操作都是基于 nginx。

  1. FROM <image> [AS <name>]
  2. FROM <image>[:<tag>] [AS <name>]
  3. FROM <image>[@<digest>] [AS <name>]

没有指定tag 就代表使用latest的版本

  1. FROM scratch

如果以 scratch 为基础镜像的话,意味着不以任何镜像为基础,接下来所写的指令将作为镜像第一层开始存在。

RUN

用于执行后面跟着的命令行命令。有以下俩种格式:
1.RUN <命令行命令> 等同于,在终端操作的 shell 命令
2.RUN ["可执行文件", "参数1", "参数2"]
eg:
RUN [“./test.php”, “dev”, “offline”] 等价于 RUN ./test.php dev offline
注意:Dockerfile 的指令每执行一次都会在 docker 上新建一层。所以过多无意义的层,会造成镜像膨胀过大,任何无关的东西都应该清理掉。不需要的中间文件

  1. FROM centos
  2. RUN yum -y install wget
  3. RUN wget -O redis.tar.gz "http://download.redis.io/releases/redis-5.0.3.tar.gz"
  4. RUN tar -xvf redis.tar.gz

可简化为以下格式,用&& 连接,同时可以删除掉没有用的 redis.tar.gz:

  1. FROM centos
  2. RUN yum -y install wget \
  3. && wget -O redis.tar.gz "http://download.redis.io/releases/redis-5.0.3.tar.gz" \
  4. && tar -xvf redis.tar.gz
  5. && rm redis.tar.gz
  1. apt-get remove 会删除软件包而保留软件的配置文件
  2. apt-get purge 会同时清除软件包和软件的配置文件

COPY

  1. COPY <src> <dest>
  1. WORKDIR /app
  2. COPY nickdir .

注意: 只复制目录下面的内容,而不复制目录本身,如果需要复制目录本身需要指定这个目录的名称

  1. WORKDIR /app
  2. COPY nickdir ./nickdir

ADD

  1. ADD <src> <dest>

特殊作用1:解压压缩文件并把它们添加到镜像中

  1. WORKDIR /app
  2. ADD nickdir.tar.gz .

特殊作用2:从 url 拷贝文件到镜像中
下面的两段代码来自 docker 官方文档

  1. ADD http://example.com/big.tar.xz /usr/src/things/
  2. RUN tar -xJf /usr/src/things/big.tar.xz -C /usr/src/things
  3. RUN make -C /usr/src/things all

在 docker 官方文档的最佳实践中却强烈建议不要这么用!!docker 官方建议我们当需要从远程复制文件时,最好使用 curl 或 wget 命令来代替 ADD 命令。原因是,当使用 ADD 命令时,会创建更多的镜像层,当然镜像的 size 也会更大
如果使用下面的命令,不仅镜像的层数减少,而且镜像中也不包含 big.tar.xz 文件:

  1. RUN mkdir -p /usr/src/things \
  2. && curl -SL http://example.com/big.tar.xz \
  3. | tar -xJC /usr/src/things \
  4. && make -C /usr/src/things all

CMD

如果用户启动容器run时指定了运行的命令,则会覆盖掉CMD指定的命令,出现多次,只有最后一个有效。

  1. CMD <command> param1 param2 #shell 模式
  2. CMD ["executable","param1","param2"] #exec模式
  3. CMD ["param1","param2"] # 作为ENTRYPOINT指令的默认参数

当 ENTRYPOINT 与 CMD 同时给出时,CMD 中的内容会作为 ENTRYPOINT 定义命令的参数,最终执行容器启动的还是 ENTRYPOINT 中给出的命令。

ENTRYPOINT

ENTRYPOINT的指令不会被docker run 运行的命令项所覆盖。如果需要覆盖ENTRYPOINT的指令,需要使用docker run —entrypoint

  1. ENTRYPOINT <command> param1 param2 #shell 模式
  2. ENTRYPOINT ["executable","param1","param2"] #exec模式

ENV

设置容器的环境变量,ENV 通过-e 设置 docker run 传参。

  1. EVN <key> <value> #只能设置一个
  2. EVN <key>=<value>#允许一次设置多个

eg:

  1. FROM alpine
  2. ENV animals="turtle, monkey, goose"
  1. docker run -it -e animals="mouse,rat,kangaroo" image

ARG

ARG指令用于docker build设置构建参数,类似于ENV。和ENV不同的是,ARG设置的是构建时的环境变量,在容器运行时是不会存在这些变量的。创建一个Dockerfile文件 内容如下
eg:

  1. FROM alpine
  2. ARG runmode=PRO
  3. ENV env=$runmode
  4. CMD echo $env

执行dockerfile创建镜像baxiang/alpine
ARG 通过 --build-arg接收docker build 时传入的参数

  1. $ docker build -t baxiang/alpine --build-arg runmode=dev ./

创建容器,获取当前的环境变量参数

  1. $ docker run -it baxiang/alpine sh
  2. / # echo $env
  3. dev

VOLUME

容器内目录/tmp 和 /usr/tmp,匿名挂载映射到宿主机

  1. FROM java:8
  2. VOLUME /tmp /usr/tmp
  3. COPY /target/springbootdemo.jar app.jar
  4. RUN bash -c 'touch /app.jar'
  5. EXPOSE 10001
  6. ENTRYPOINT ["java","-jar","/app.jar"]

Source是宿主机目录,Destination是容器内目录

  1. $ docker inspect add8a379065c
  2. "Mounts": [
  3. {
  4. "Type": "volume",
  5. "Name": "3c18486ccfe419156ef62d346d29f6668ec34a236497c47f7e7907e95c310d0e",
  6. "Source": "/var/lib/docker/volumes/3c18486ccfe419156ef62d346d29f6668ec34a236497c47f7e7907e95c310d0e/_data",
  7. "Destination": "/tmp",
  8. "Driver": "local",
  9. "Mode": "",
  10. "RW": true,
  11. "Propagation": ""
  12. },
  13. {
  14. "Type": "volume",
  15. "Name": "c5b6e1e0f6db6e70f15d836caa9663173e4bd8e23db1817146c31348d931a43b",
  16. "Source": "/var/lib/docker/volumes/c5b6e1e0f6db6e70f15d836caa9663173e4bd8e23db1817146c31348d931a43b/_data",
  17. "Destination": "/usr/tmp",
  18. "Driver": "local",
  19. "Mode": "",
  20. "RW": true,
  21. "Propagation": ""
  22. }
  23. ]

运行时可以覆盖这个挂载设置。执行:-v mydata:/data,就使用了本地 mydata 这个命名卷挂载到了 /data 这个位置,替代了 Dockerfile 中定义的匿名卷的挂载配置。

  1. docker run --name ubuntu2 -v ~/mytmp:/tmp dengxiaotian/ubuntu
  1. "Mounts": [
  2. {
  3. "Type": "bind",
  4. "Source": "/home/dengxiaotian/mytmp",
  5. "Destination": "/tmp",
  6. "Mode": "",
  7. "RW": true,
  8. "Propagation": "rprivate"
  9. }
  10. ],

EXPOSE

  1. EXPOSE <端口1> [<端口2>...]

EXPOSE 指令是声明运行时容器提供服务端口,这只是一个声明,在运行时并不会因为这个声明应用就会开启这个端口的服务。在 Dockerfile 中写入这样的声明有两个好处,一个是帮助镜像使用者理解这个镜像服务的守护端口,以方便配置映射;另一个用处则是在运行时使用随机端口映射时,也就是 docker run -P时,会自动随机映射 EXPOSE 的端口。
eg:

  1. # 暴露多个端口;
  2. EXPOSE port1 port2 port3
  3. # 如果想代理EXPOSE端口, 相应的运行容器使用的命令;
  4. # 宿主端口随机
  5. $ docker run -p port1 -p port2 -p port3 image
  6. # 还可以指定需要映射到宿主机器上的某个端口号;
  7. # 指定宿主主机端口
  8. $ docker run -p host_port1:port1 -p host_port2:port2 -p host_port3:port3 image
  1. -p,是映射宿主端口和容器端口,换句话说,就是将容器的对应端口服务公开给外界访问,而 EXPOSE 仅仅是声明容器打算使用什么端口而已,并不会自动在宿主进行端口映射。例如,如果你想在宿主机上访问对应port1端口的服务 时,需要使用命令docker run -p 宿主机端口:port1 image将端口进行映射。
  2. EXPOSE只是起到了声明作用,不是说我写了80端口,这个容器就只能使用80了,如果你想5000端口也可以向外暴露,也可以使用命令:docker run -p 宿主机端口:5000 image

    WORKDIR

    为RUN、CMD、ENTRYPOINT、COPY和ADD设置工作目录,如果当前目录不存在会自动创建 ```bash FROM ubuntu:18.04 WORKDIR /eventrisk

COPY ./conf/ ./conf/ COPY ./resources/ ./resources/ COPY eventrisk .

CMD [“./eventrisk”]

  1. <a name="VL4Px"></a>
  2. ## USER
  3. ```bash
  4. FROM jenkinsci/blueocean:latest
  5. USER root

指定运行容器时的用户名或UID,后续的RUN、CMD、ENTRYPOINT也会使用指定用户

LABEL

LABEL 指令用来给镜像添加一些元数据(metadata),以键值对的形式,语法格式如下:

  1. LABEL <key>=<value> <key>=<value> <key>=<value> ...

eg:

  1. LABEL org.opencontainers.image.authors="runoob"
  2. # 用/实现换行
  3. LABEL description="This text illustrates \
  4. that label-values can span multiple lines."

HEALTHCHECK

  1. FROM nginx:latest
  2. COPY test.txt /test.txt
  3. HEALTHCHECK --interval=5s --timeout=3s CMD cat /test.txt || exit 1

image.png

  1. rm test.txt

image.png
可以用 docker inspect 来查看unhealth 的原因

ONBUILD

用的较少,用到的时候进行记录

tips:

docker push 发布到dockerhub 或者阿里云
image.png
点击tag跳转到Dockerfile
image.png