Dockerfile
1、Dockerfile的常用命令
指令 | 作用 |
---|---|
FROM | 当前镜像是基于哪个镜像的 第一个指令必须是FROM |
MAINTAINER | 镜像维护者的姓名和邮箱地址 |
RUN | 构建镜像时需要运行的指令 |
EXPOSE | 当前容器对外暴露出的dockerfile端口号 |
WORKDIR | 指定在创建容器后,终端默认登录进来的工作目录,一个落脚点 |
ENV | 用来在构建镜像过程中设置环境变量 |
ADD | 将宿主机目录下的文件拷贝进镜像且ADD命令会自动处理URL和解压tar包 |
COPY | 类似于ADD,拷贝文件和目录到镜像中 将从构建上下文目录中<原路径>的文件/目录复制到新的一层的镜像内的<目标路径>位置 |
VOLUME | 容器数据卷,用于数据保存和持久化工作 |
CMD | 指定一个容器启动时要运行的命令 Dockerfile中可以有多个CMD指令,但只有最后一个生效,CMD会被docker run之后的参数替换 |
ENTRYPOINT | 指定一个容器启动时要运行的命令 ENTRYPOINT的目的和CMD一样,都是在指定容器启动程序及其参数 |
FROM
-
基于哪个镜像进行构建新的镜像,在构建时会自动从 dockerhub 拉取 base 镜像,必须作为Dockerfile的第一个指令
-
语法:
FROM <image> FROM <image>:<tag> # 不写则会拉取 latest FROM <image>@<digest> # 摘要
MAINTAINER
-
镜像维护这的姓名或者邮箱
-
语法
MAINTAINER <name>
RUN
-
构建镜像时运行的指定命令
-
语法:
RUN mkdir logs RUN echo 'hello' # 第一个表示执行的命令,后面的表示参数 RUN RUN ["executable", "param1", "param2"] (exec form)
EXPOSE
-
指定容器内对外暴露的端口
-
语法:
EXPOSE 8080 EXPOSE 8989
WORKDIR
-
用来为 Dockerfile中的任何RUN、CMD、ENTRYPOINT、COPY、ADD设置工作目录,如果是 WORKDIR 不存在,即使后续不存在任何 Dockerfile 指令,也会被创建。
-
语法:
WORKDIR /var WORKDIR logs WORKDIR data # 注意:WORKDIR指令可以在Dockerfile中多次使用。如果提供了相对路径,则该路径将与先前WORKDIR指令的路径相对
ENV
-
构建容器时设置环境变量。这个值将会出现在构建中所有后续指令的环境中。
-
语法:
ENV <key> <value> ENV <key>=<value> ...
ADD
-
从当前上下文复制新文件、目录、或远程文件url,并将它们添加到指定目录的映射文件中。
-
如果源文件为一个 tar 压缩文件,压缩格式为 gzip、bzip、以及xz的情况下,ADD会自动将这个压缩文件解压缩到
目标路径中
-
语法:
ADD home* /mydir/ # 通配符添加多个文件 ADD hom?.txt /mydir/ # 通配符 ADD test.txt relativeDir/ # 相对路径 ADD test.txt /myidr/test.txt# 绝对路径 ADD url
COPY
-
从当前上下文复制到镜像指定目录中
-
除了不能自动解压和不能复制网络文件外,其他的与ADD别无二致
-
语法:
COPY <src> <dest> COPY demo.jar /apps/demo.jar
VOLUME
-
用来定义容器运行时可以挂载到宿主机的目录
-
这个命令不能指定宿主机需要挂载的路径,默认为
/var/lib/docker
目录下创建临时文件。不如 -v 方便。 -
语法:
VOLUME ["path"]
CMD
-
用来
run
时容器指定执行的命令,在Dockerfile中只能有一条CMD命令,存在多条下面会覆盖上面的。 -
语法:
CMD ["executable","param1","param2"] # 命令+参数 CMD ["param1","param2"] # 如果指定了 ENTRYPOINT CMD则就作为 ENTRYPOINT 的参数 CMD command param1 param2 # shell 命令
ENTRYPOINT
-
用来指定容器启动时执行的命令和CMD类似
-
语法:
ENTRYPOINT ["executable", "param1", "param2"]
CMD 和 ENTRYPOINT 的区别
- ENTRYPOINT:一般用于设置容器启动后的第一个命令,对这个容器来说往往是固定的。
- CMD:往往用于设置容器启动的第一个命令的默认参数,对这个容器来说是可以变化的。
-
CMD 里面的命令在运行时可以被覆盖
docker run 镜像:版本号 覆盖自己定义的命令 ls /
-
ENTRYPOINT 里面命令如何在运行容器时进行覆盖
docker run --entrypoint=覆盖指令 镜像:版本号 传递的参数
-
ENTRYPINT 和 CMD 配合使用
ENTRYPINT 用来写一个容器的固定指令
CMD 用来给 ENTRYPINT 指定参数
ENTRYPINT ["ls"] CMD ["/apps/data"]
注意:这种配置必须使用json数组写法。
2、Dockerfile打包容器
- 这个命令需要在Dockerfile所在目录下运行
- 命令:
docker build -t <容器名>:<版本号> .
3、使用Dockerfile启动一个jar
1、编写 Dockerfile
FROM openjdk:8-jdk
ENV path=/apps
MAINTAINER 123789@163.com
WORKDIR $path
# dockerfile 和 demo.jar在同一个目录
ADD demo.jar $path/demo.jar
EXPOSE 8888
ENTRYPOINT ["java","-jar"]
CMD ["demo.jar"]
2、打包容器
docker build -t demo:1.0 .
3、启动容器
docker run -d -p 8888:8888 --name demo demo:1.0
4、使用dockerfile + shell脚本启动多个jar
1、编写Dockerfile
FROM openjdk:8-jdk
ENV path=/apps
MAINTAINER 123789@163.com
WORKDIR $path
# dockerfile 和 demo1/demo2.jar在同一个目录
ADD demo1.jar $path/demo1.jar
ADD demo2.jar $path/demo2.jar
ADD start.sh $path/start.sh
EXPOSE 8888
EXPOSE 9999
RUN mkdir -p $path/logs
RUN chmod +x $path/start.sh
ENTRYPOINT ["sh","-c"]
CMD ["/apps/start.sh"]
2、编写 Shell 脚本
#!/bin/bash
echo "开始启动"
nohup java -jar /apps/demo1.jar>/apps/logs/mo_demo1.log &
echo "demo1 启动成功,开始启动 demo2"
nohup java -jar /apps/demo2.jar>/apps/logs/mo_demo2.log &
echo "demo2 启动成功"
# 死循环,保持docker前台运行
while [[ true ]]; do
sleep 1
done
3、打包容器
docker build -t demo:1.2 .
4、运行容器
docker run -d -p 8888:8888 -p 9999:9999 --name demo demo:1.2
Dockerfile+shell遇到的问题
在启动容器的时候出现了启动容器后里面就停止的情况,但是没有任何报错。
原因:
- docker 容器中必须有一个处于前台运行,如果没有前台执行,容器就会认为是空闲状态,就会自动退出。
解决方案:
- 在 shell 脚本中编写一个死循环,让docker一直保持前台运行状态。
- 在 shell 脚本中,将最后一个
jar
包启动取消后台运行,也就是不添加 “&” 符号