使用Dockerfile构建Docker镜像

使用Dockerfile构建Docker镜像

1、什么是DockerFile

Docker是用于构建Docker镜像的脚本文件,通过这个脚本可以构建自己的docker镜像。

2、第一个dockerfile

# docker的镜像是分层的,所以我们可以指定一个基础的镜像
FROM java:8

# 作者
MAINTAINER rayfoo@qq.compp

#  挂载目录 镜像挂载后 容器就无需手动挂载
VOLUME /app

# 将jar包添加到容器中 /app/目录并更名为xxx.jar
ADD ./target/Vantee-Admin-0.0.1.jar /app/Vantee-Admin-0.0.1.jar

3、构建docker镜像

# 语法
docker build -f /path/dockerfile -t imagesName:tag .

# 案例  注意最后的.
docker build -f /opt/dockerfile -t springboot-demo:1.0 .

4、Dockerfile常用指令说明

4.1、FROM(指定基础镜像)

使用FROM命令可以指定一个镜像做为基础镜像,此命令必须为首行

# 格式
FROM <image>
FROM <image>:<tag>

# 示例
FROM mysql:5.7.25

4.2、MAINTAINER(作者信息)

# 格式
MAINTAINER <name>

# 示例
MAINTAINER rayfoo
MAINTAINER zhang rui feng
MAINTAINER rayfoo@qq.com

4.3、RUN(构建镜像时执行的命令)

# 格式
RUN <command>

# 示例
RUN mkdir -p /app

4.4、ADD(复制宿主机文件到镜像,并自动解压)

# 格式
ADD <src> <dest>
ADD ["src","dest"]  #支持包含空格的文件名或路径

# 示例
ADD ./target/Vantee-Admin-0.0.1.jar /app/Vantee-Admin-0.0.1.jar
ADD ["/opt/docker demo","/opt/docker"]

# src可以使用通配符*和?,分别指多个,单个字符

# 将opt下所有以hel开头的文件复制到镜像的opt内
ADD /opt/hel* /opt
# 以hell开头 且长度为5的文件复制到opt内
ADD /opt/hell? /opt

4.5、COPY(复制宿主机文件到镜像)

与ADD相同,不具备解压功能。略

4.6、CMD(构建容器时调用的命令)

此命令中的语句构建容器时,才会被执行

# 格式
CMD <command>
# exec模式
CMD ["command","params","params"]

# 示例
CMD mkdir -p /app
CMD cd /app
CMD echo "hello world"

4.7、ENTRYPOINT(配置容器)

其用法类似于CMD,但是一个Dockerfile中只允许存在一个,一般做为Dockerfile的入口。docker容器启动参数也可以加上--entrypoint来覆盖它。比如你可以在SpringBoot的镜像中,添加启动jar包的命令

如果同时存在CMD和ENTRYPOINT

  • 在exec模式下CMD会做为ENTRYPOINT的参数
  • 在shell模式下CMD会被忽略
  • 如果 ENTRYPOINT 使用了 exec 模式,CMD 也应该使用 exec 模式。
  • 中括号的形式为exec模式
  • 直接输入的格式为shell格式
ENTRYPOINT ["java","-Xms512m","-Xmx512m","-Djava.security.egd=file:/dev/./urandom","-jar","/app/Vantee-Admin-0.0.1.jar", "--spring.profiles.active=dev", "--server.port=10000"]
"-Xms512m","-Xmx512m" 可以指定JVM内存启动

参考 https://www.jb51.net/article/136264.htm

4.8、shell模式和exec模式

exec 模式

exec 模式的特点是不会通过 shell 执行相关的命令,所以像 $HOME 这样的环境变量是取不到的:

FROM centos:7
CMD [ "echo", "$HOME" ]

通过上面的 Dockerfile 文件构建的镜像,运行以后,只会输出:$HOME。

通过 exec 模式执行 shell 可以获得环境变量:

FROM centos:7
CMD ["sh", "-c", "echo $HOME"]

通过上面的 Dockerfile 文件构建的镜像,运行以后,会输出:/root。

shell 模式

使用 shell 模式时,docker 会以 /bin/sh -c "task command" 的方式执行任务命令。

FROM centos:7
CMD echo $HOME

通过上面的 Dockerfile 文件构建的镜像,运行以后,会输出:/root。
原文链接:https://blog.csdn.net/wxy_csdn_world/article/details/116860193

4.9、LABEL(为镜像添加元数据)

# 格式
LABEL <key>=<value> <key>=<value> <key>=<value>

# 示例
LABEL version="1.0" description="这是一个Web服务器" by="IT笔录"

4.10、EVN(设置环境变量)

# 格式:
#<key>之后的所有内容均会被视为其<value>的组成部分,因此,一次只能设置一个变量
ENV <key> <value>  
 #可以设置多个变量,每个变量为一个"<key>=<value>"的键值对,如果<key>中包含空格,可以使用来进行转义,也可以通过""来进行标示;另外,反斜线也可以用于续行
ENV <key>=<value> ... 

# 示例:
ENV myName John Doe
ENV myDog Rex The Dog
ENV myCat=fluffy

4.11、EXPOSE(指定与外界交互的端口)

# 格式:
EXPOSE <port> [<port>...]

# 示例:
EXPOSE 80 443
EXPOSE 8080
EXPOSE 11211/tcp 11211/udp

# EXPOSE并不会让容器的端口访问到主机。要使其可访问,需要在docker run运行容器时通过-p来发布这些端口,或通过-P参数来发布EXPOSE导出的所有端口

4.12、VOLUME(指定需要映射到宿主机的目录)

# 格式:
VOLUME ["/path/to/dir"]

# 示例:

VOLUME ["/data"]
VOLUME ["/var/www", "/var/log/apache2", "/etc/apache2"]

# 和EXPOSE一样,如果需要映射具体的文件夹,需要手动指定

一个卷可以存在于一个或多个容器的指定目录,该目录可以绕过联合文件系统,并具有以下功能:

  • 卷可以容器间共享和重用
  • 容器并不一定要和其它容器共享卷
  • 修改卷后会立即生效
  • 对卷的修改不会对镜像产生影响
  • 卷会一直存在,直到没有任何容器在使用它

4.13、WORKDIR(指定工作目录,类似于cd)

# 格式:
WORKDIR /path/to/workdir

# 示例:
WORKDIR /a  (这时工作目录为/a)
WORKDIR b  (这时工作目录为/a/b)
WORKDIR c  (这时工作目录为/a/b/c) 

# 通过WORKDIR设置工作目录后,Dockerfile中其后的命令RUN、CMD、ENTRYPOINT、ADD、COPY等命令都会在该目录下执行。在使用docker run运行容器时,可以通过-w参数覆盖构建时所设置的工作目录。

4.14、USER(指定允许运行容器的用户)

# 格式:  
USER user  
USER user:group  
USER uid  
USER uid:gid  
USER user:gid  
USER uid:group

# 示例:      
USER www

# 使用USER指定用户后,Dockerfile中其后的命令RUN、CMD、ENTRYPOINT都将使用该用户。镜像构建完成后,通过docker run运行容器时,可以通过-u参数来覆盖所指定的用户。

4.15、ARG(用于指定传递给构建运行时的变量

# 格式:
ARG <name>[=<default value>]

# 示例:
ARG site
ARG build_user=www

4.16、ONBUILD(用于设置镜像的触发器)

# 格式:  
ONBUILD [INSTRUCTION]

# 示例:
ONBUILD ADD . /app/src
ONBUILD RUN /usr/local/bin/python-build --dir /app/src

#当所构建的镜像被用做其它镜像的基础镜像,该镜像中的触发器将会被触发

5、Docker容器内的应用无法连接数据库

有可能是时区不同步,可以尝试一下下面的办法:

在dockerfile中添加如下配置

# 同步时区
ENV TZ=Asia/Shanghai
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone

原文地址:https://www.cnblogs.com/zhangruifeng/p/14801218.html