什么是Dockerfile

Dockerfile可以认为是Docker镜像的描述文件,是由一系列命令和参数构成的脚本。主要作用是用来构建docker镜像的构建文件

image-20210213102047171

  • 通过架构图可以看出通过DockerFile可以直接构建镜像

为什么要使用Dockerfile

问题:在docker hub中官方提供了很多镜像的,已经能满足我们的所有服务,为什么还需要自定义镜像呢?

核心作用:是将我们自己的应用打包成镜像,这样就可以使我们的应用容器运行。

也可将基础的镜像,根据自己的配置,进行重新构建镜像,日后以便复用。

Dockerfile解析过程

image-20210213103317114

Dockerfile的常用语法命令

官方说明:https://docs.docker.com/engine/reference/builder/

保留字 作用
FROM 当前镜像是基于哪个镜像的 第一个指令必须是FROM
MAINTAINER 镜像维护者的姓名和邮箱地址(已废弃)
RUN 构建镜像时需要运行的指令
EXPOSE 当前容器对外暴露出的端口号
WORKDIR 指定在创建容器后,终端默认登录进来的工作目录,一个落脚点
ENV 用来在构建镜像过程中设置环境变量
ADD 将宿主机目录下的文件拷贝进镜像且ADD命令会自动处理URL和解压tar包
COPY 类似于ADD,拷贝文件和目录到镜像中
将从构建上下文目录中<原路径>的文件/目录复制到新的一层的镜像内的<目标路径>位置
VOLUME 容器数据卷,用于数据保存和持久化工作
CMD 指定一个容器启动时要运行的命令
Dockerfile中可以有多个CMD指令,但只有最后一个生效,CMD会被docker run之后的参数替换
ENTRYPOINT 指定一个容器启动时要运行的命令
ENTRYPOINT的目的和CMD一样,都是在指定容器启动程序及其参数

1. FROM 命令

  • 基于那个镜像进行构建新的镜像,在构建时会自动从docker hub拉取base镜像 必须作为Dockerfile的第一个指令出现

  • 语法:

    1
    2
    3
    FROM  <image>
    FROM <image>[:<tag>] 使用版本不写为latest
    FROM <image>[@<digest>] 使用摘要

2. MAINTAINER 命令

  • 镜像维护者的姓名和邮箱地址[已废弃]

  • 语法:

    1
    MAINTAINER <name>

3. RUN 命令

  • RUN指令将在当前映像之上的新层中执行任何命令并提交结果。生成的提交映像将用于Dockerfile中的下一步

  • 语法:

    1
    2
    3
    4
    5
    RUN <command> (shell form, the command is run in a shell, which by default is /bin/sh -c on Linux or cmd /S /C on Windows)
    RUN echo hello

    RUN ["executable", "param1", "param2"] (exec form)
    RUN ["/bin/bash", "-c", "echo hello"]

4. EXPOSE 命令

  • 用来指定构建的镜像在运行为容器时对外暴露的端口

  • 语法:

    1
    2
    EXPOSE 80/tcp  如果没有显示指定则默认暴露都是tcp
    EXPOSE 80/udp

5. WORKDIR 命令

  • 用来为Dockerfile中的任何RUN、CMD、ENTRYPOINT、COPY和ADD指令设置工作目录。如果WORKDIR不存在,即使它没有在任何后续Dockerfile指令中使用,它也将被创建。

  • 语法:

    1
    2
    3
    4
    5
    WORKDIR /path/to/workdir

    WORKDIR /a
    WORKDIR b
    WORKDIR c

    注意:WORKDIR指令可以在Dockerfile中多次使用。如果提供了相对路径,则该路径将与先前WORKDIR指令的路径相对

6. ENV 命令

  • 用来为构建镜像设置环境变量。这个值将出现在构建阶段中所有后续指令的环境中。

  • 语法:

    1
    2
    ENV <key> <value>
    ENV <key>=<value> ...

7. ADD 命令

  • 用来从context上下文复制新文件、目录或远程文件url,并将它们添加到位于指定路径的映像文件系统中。

  • 语法:

    1
    2
    3
    4
    5
    ADD hom* /mydir/       通配符添加多个文件
    ADD hom?.txt /mydir/ 通配符添加
    ADD test.txt relativeDir/ 可以指定相对路径
    ADD test.txt /absoluteDir/ 也可以指定绝对路径
    ADD url / 可以指定工程的连接进行下载到指定的目录

8. COPY 命令

  • 用来将context目录中指定文件复制到镜像的指定目录中

  • 语法:

    1
    2
    COPY src dest
    COPY ["<src>",... "<dest>"]

9. VOLUME 命令

  • 用来定义容器运行时可以挂在到宿主机的目录

  • 语法:

    1
    VOLUME ["/data"]

10. CMD 命令

  • 用来为启动的容器指定执行的命令,在Dockerfile中只能有一条CMD指令。如果列出多个命令,则只有最后一个命令才会生效。

  • 注意: Dockerfile中只能有一条CMD指令。如果列出多个命令,则只有最后一个命令才会生效。

  • 语法:

    1
    2
    3
    CMD ["executable","param1","param2"] (exec form, this is the preferred form)
    CMD ["param1","param2"] (as default parameters to ENTRYPOINT)
    CMD command param1 param2 (shell form)

11. ENTRYPOINT命令

  • 用来指定容器启动时执行命令和CMD类似

  • 语法:

    1
    2
    ENTRYPOINT ["executable", "param1", "param2"]
    ENTRYPOINT command param1 param2
    • ENTRYPOINT指令,往往用于设置容器启动后的第一个命令,这对一个容器来说往往是固定的。
    • CMD指令,往往用于设置容器启动的第一个命令的默认参数,这对一个容器来说可以是变化的。

Dockerfile构建镜像

在 Dockerfile 文件的存放目录下,执行构建动作:

  • docker build -t 镜像名称:[tag] .
  • 注意:后面有个点(.)千万不能忽略,如果不写tag则默认是latest

实战:Dockerfile构建SpringBoot应用

  1. 准备SpringBoot可运行项目

  2. 服务器中创建Dockerfile上下文目录context

    • 任意创建一个目录:mkdir demo
  3. 在上一步创建的目录下,新建Dockerfile文件

    1
    2
    3
    4
    [root@localhost ~]# cd demo
    [root@localhost demo]# touch Dockerfile
    [root@localhost demo]# ls
    Dockerfile
  1. 获取打包完成的jar并上传至部署的服务器中的上下文目录

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    bogon:spring-boot-restful-api jinglv$ ls
    README.md pom.xml src
    checkstyle spring-boot-restful-api.iml target
    bogon:spring-boot-restful-api jinglv$ cd target/
    bogon:target jinglv$ ls
    checkstyle-cachefile classes maven-status
    checkstyle-checker.xml generated-sources spring-boot-restful-api-0.0.1-SNAPSHOT.jar
    checkstyle-result.xml maven-archiver spring-boot-restful-api-0.0.1-SNAPSHOT.jar.original
    bogon:target jinglv$ scp spring-boot-restful-api-0.0.1-SNAPSHOT.jar root@192.168.1.115:/root/demo
    root@192.168.1.115's password:
    spring-boot-restful-api-0.0.1-SNAPSHOT.jar 100% 32MB 46.1MB/s 00:00
  1. 编写Dockerfile

    1
    2
    3
    4
    5
    6
    FROM openjdk:8
    WORKDIR /api
    ADD spring-boot-restful-api-0.0.1-SNAPSHOT.jar api.jar
    EXPOSE 8088
    ENTRYPOINT ["java","-jar"]
    CMD ["api.jar"]
  • FROM:基于镜像进行构建,如果是war包则是基于tomcat
  • WORKDIR:定义进入容器时默认位置,接下来后续操作工作位置
  • ADD:将上面的spring-boot-restful-api-0.0.1-SNAPSHOT.jar的jar包复制到工作目录,同时修改其名为api.jar
  • EXPOSE:当前容器暴露哪个端口,因为项目使用端口是8088
  • ENTRYPOINT:启动应用固定命令
  • CMD:执行jar
  1. 构建镜像

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    [root@localhost demo]# docker build -t api .
    Sending build context to Docker daemon 33.64MB
    Step 1/6 : FROM openjdk:8
    8: Pulling from library/openjdk
    b9a857cbf04d: Already exists
    d557ee20540b: Already exists
    3b9ca4f00c2e: Already exists
    667fd949ed93: Already exists
    661d3b55f657: Already exists
    60cfec2a948e: Pull complete
    79ee4b4b7121: Pull complete
    Digest: sha256:b253b93dc528967eff64ade00a9079dc464fb75b9d27a7a578c8006ca0645de8
    Status: Downloaded newer image for openjdk:8
    ---> 8ca4a86e32d8
    Step 2/6 : WORKDIR /api
    ---> Running in 202d8c20a39d
    Removing intermediate container 202d8c20a39d
    ---> c8108d4b5491
    Step 3/6 : ADD spring-boot-restful-api-0.0.1-SNAPSHOT.jar api.jar
    ---> 74379d1de17c
    Step 4/6 : EXPOSE 8088
    ---> Running in a10fdc264ac3
    Removing intermediate container a10fdc264ac3
    ---> f0b514cc7c02
    Step 5/6 : ENTRYPOINT ["java","-jar"]
    ---> Running in ae146c0d6b17
    Removing intermediate container ae146c0d6b17
    ---> 0e359f8ab6de
    Step 6/6 : CMD ["api.jar"]
    ---> Running in 84b2aa3efc52
    Removing intermediate container 84b2aa3efc52
    ---> e3c3287903c9
    Successfully built e3c3287903c9
    Successfully tagged api:latest
    [root@localhost demo]# docker images
    REPOSITORY TAG IMAGE ID CREATED SIZE
    api latest e3c3287903c9 10 seconds ago 547MB
  1. 运行镜像

    1
    2
    3
    4
    5
    [root@localhost demo]# docker run -d --name api -p 8088:8088 api
    160c52c651c18ad35f02d4e4f618bb827b7e865d5ff4856a6fe0aa32883b6f7f
    [root@localhost demo]# docker ps
    CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
    160c52c651c1 api "java -jar api.jar" 7 seconds ago Up 3 seconds 0.0.0.0:8088->8088/tcp api
  1. 访问项目

    image-20210213165807948

Idea中安装Docker插件

  1. 搜索Docker插件进行安装,安装成功后重启Idea

    image-20210213170047860

  2. 在工程目录下,创建Dockerfile文件,并编写Dockerfile的内容

    image-20210213170504380

Idea连接远程SFTP

  1. idea菜单栏Tools -> Deploymet -> Browse Remote Host

    image-20210213171541625

  2. 打开“Remote Host”界面,进行远程服务的添加

    image-20210213171751605

  3. 新增SFTP协议远程服务

    image-20210213171919769

    image-20210213172010394

    image-20210213172113021

    image-20210213172210252

    image-20210213172241965

    image-20210213172346542

  4. 完成以上配置后,我们就可以看到服务器的目录

    image-20210213172443452

    这时,我们就可以在Idea里面,对服务器进行操作,比如:新建文件/目录,拖拽文件到服务器目录等……