使用
docker build -t 镜像名称[:镜像标签] -f Dockerfile所在目录 .
例如 docker build -t myapp . 那么将会根据当前路径里的Dockerfile构建一个名为myapp的镜像;
注意,-f才是指定dockerfile路径,后面的点是镜像构建上下文
常用标签
FROM
FROM:定制的镜像都是基于 FROM 的镜像
RUN
run在docker build时执行,cmd在docker run时执行
RUN有两种形式:
- RUN (如同执行shell命令 - /bin/sh -c)
- RUN [“executable”, “param1”, “param2”] (exec形式)
exec形式被解析为JSON数组,这意味着必须使用双引号(“),而不是单引号(’)
CMD
指定启动容器后,提供默认命令及参数,会被docker run 后面参数替换
dockerfile中可以有多条cmd命令,但只是最后一条有效
格式:
- CMD <shell 命令> (shell form)
- CMD ["<可执行文件或命令>","","",…] (exec form)
- CMD ["","",…] # 该写法是为 ENTRYPOINT 指令指定的程序提供默认参数
推荐使用第二种格式,执行过程比较明确。
第一种格式实际上在运行的过程中也会自动转换成第二种格式运行,但这样docker会在指定的命令前加 /bin/sh -c 执行,可能会出问题;
exec形式被解析为JSON数组,这意味着必须使用双引号(“),而不是单引号(’)
例如使用第2种格式
Dockerfile
FROM centos
CMD ["echo", "this is a echo test" , "this is a echo test"]
构建
docker build -t mycentos .
运行
docker run mycentos
输出
this is a echo test this is a echo test
ENTRYPOINT
在Dockerfile中,只能有一个ENTRYPOINT指令,如果有多个ENTRYPOINT指令则以最后一个为准。
在Dockerfile中,ENTRYPOINT指令或CMD指令,至少必有其一。
Entrypoint指令用于设定容器启动时第一个运行的命令及其参数。
执行docker run如果带有其他命令参数,不会覆盖ENTRYPOINT指令,并且会被作为ENTRYPOINT指令的参数。
ENTRYPOINT ["executable", "param1", "param2"] // 这是 exec 模式的写法,注意需要使用双引号。
ENTRYPOINT command param1 param2 // 这是 shell 模式的写法。
CMD作为ENTRYPOINT的参数
FROM ubuntu
...
ENTRYPOINT ["echo"]
CMD ["defaultvalue"]
构建
docker build -t mycentos .
运行
docker run mycentos
输出
defaultvalue
同理,docker run mycentos aaa会输出aaa,因为aaa会覆盖Dockerfile里的CMD命令
例子
FROM frolvlad/alpine-oraclejdk8
VOLUME /tmp
COPY ./xxx.jar app.jar
RUN sh -c "touch /app.jar"
EXPOSE 8088
ENTRYPOINT ["java", "-jar", "app.jar"]
VOLUME
通过dockerfile的 VOLUME 指令可以在镜像中创建挂载点,这样只要通过该镜像创建的容器都有了挂载点。
注意
-
通过 VOLUME 指令创建的挂载点,无法指定主机上对应的目录,是自动生成的。
-
通过docker run没有指定-v命令(或者docker compose 中没有指定volume命令) docker会创建一个匿名的volume,与主机/var/lib/docker/容器id/_data目录对应。
- 例如,DockerFile中指定VOLUME /tmp,而docker run中没有指定-v命令,那么docker将自动把容器/tmp目录挂载到宿主机/var/lib/docker/容器id/_data目录下
-
docker run -v命令如果同时指定了宿主机目录和容器目录,那么Dockerfile volume命令或被覆盖
-
容器数据持久化,删除容器,映射的主机目录数据不会变