• Dockerfile


    目录

    一、Dockerfile介绍

    ①dockerfile原理(镜像分层)

    ②镜像结构

    container:容器层

    images:镜像层

    rootfs:基础层

    bootfs:内核层

    ③Dockerfile结构

    ④为什么docker中centos7镜像大小只有200M上下

    二、Dockerfile命令

    ①FROM

    ②MAINTAINER和USER

    ③RUN

    ④CMD和ENTRYPOINT

    4.1CMD、ENTRYPOINT

    ⑤EXPOSE

    ⑥ENV

    ⑦ADD和COPY

    ⑧VOLUME

    ⑨WORKDIR

    三、dockerfile构建一个Tomcat镜像

    ①编写dockerfile

    ②创建镜像并运行

    ③网页浏览tomcat

     


    一、Dockerfile介绍

    dockerfile是一个文本文件,其中包含了一条条指令(instruction),用于构建镜像。每一条指令构建一层镜像,因此每一条指令的内容,就是描述该层镜像应当如何构建。虽然在dockerhub中官方提供的很多镜像已经能满足我们的所有服务,但总归有足够个性化的功能是其覆盖不到的,这就体现出dockerfile编写的必要性,它就相当于“创意工坊”,让编写者可以根据不同的使用环境、方向,不同的功能需求,制定编写个性化的,不尽相同的dockerfile,并在这个镜像基础上搭建运行容器

    构建过程

    编写dockerfile文件 ===》“docker build”构建镜像 ===》“docker run”运行容器

    ①dockerfile原理(镜像分层)

    (1)Dockerfile中的每个指令都会创建一个新的镜像层(是一个临时的容器,执行完后将不再存在,再往后进行重新的创建与操作)

    (2)镜像层将被缓存和复用(后续的镜像层将基于前面的一层,每一层都会有下面几层的缓存)

    (3)当dockerfile的指令修改了,复制的文件变化了,或者构建镜像时指定的变量不同了(后续操作必然更改前面的镜像层),那么对应的镜像层缓存就会失效(自动销毁)
    (4)某一层的镜像缓存失效之后,它之后的镜像层缓存都会失效(第一层不成功,那么第二层也不成功,相当于地基)
    (5)容器的修改并不会影响镜像,如果在某一层中添加一个文件,在下一层中删除它,镜像中依然会包含该文件

    ②镜像结构

    container:容器层

    images:镜像层

    rootfs:基础层

    (root file system) 内核空间

    1. 在bootfs之上(base images, 例如centos、ubuntu)

    2. 包含的就是典型Linux 系统中的/dev, /proc, /bin, /etc 等标准目录和文件

    3. rootfs就是各种不同的操作系统发行版,比如Ubuntu,Centos等等

    bootfs:内核层

     (boot file system) 内核空间

    1.主要包含bootloader和kernel

    2.bootloader主要引导加载kernel, Linux刚启 动时会加载bootfs文件系统,在Docker 镜像的最底层是bootfs

    3.这一层与我们典型的Linux/Unix系统是一样的,包含boot加载器和内核。当boot加载完成之后整个内核就都在内存中了,此时内存的使用权已由bootfs转交给内核,此时系统也会把临时创建的bootfs这个文件系统删掉

    4.在linux操作系统中,linux加载bootfs时会将rootfs设置为read-only,系统自检后会将只读改为读写,让我们可以在操作系统中进行操作

    ③Dockerfile结构

    基础镜像信息(Linux发行版:centos ubantu suse debian alpine redhat)
    维护者信息(docker search可查看)
    镜像操作指令(tar yum make)
    容器启动时执行指令(cmd[“/root/run.sh”] 、entrypoint都是系统启动时,第一个加载的程序/脚本/命令)

    ④为什么docker中centos7镜像大小只有200M上下

    因为docker镜像只有rootfs和其他镜像层,共用宿主机的linux内核(bootfs),因此很小
    bootfs + rootfs :作用是加载、引导内核程序 + 挂载使用linux 操作系统(centos ubantu)等等一些关键的目录文件
    就是说bootsfs用内核的,rootfs用自己的
    对于一个精简的os,rootfs可以很小,只需要包括最基本的命令、工具和程序库就可以了,因为底层直接用Rost的kernel,自己只需要提供rootfs就行了。所以对于不同的linux发行版,bootfs基本是一致的,rootfs会有差别,所以不同的发行版可以公用bootfs
     

    二、Dockerfile命令

    ①FROM

    基本上都会出现在DockerFile的第一行。代表你目前的镜像来自于哪,它的基础镜像是什么。并且,如果在同一个Dockerfile中创建多个镜像时,可以使用多个 FROM 指令(每个镜像一次)

    1. FROM
    2. FROM :
    3. FROM @

    ②MAINTAINER和USER

    MAINTAINER

    指定维护者信息

    MAINTAINER 

    指定运行容器时的用户名或 UID,后续的 RUN 也会使用指定用户。
    当服务不需要管理员权限时,可以通过该命令指定运行用户。并且可以在之前创建所需要的用户,例如:RUN groupadd -r postgres && useradd -r -g postgres postgres。要临时获取管理员权限可以使用 gosu,而不推荐 sudo

    USER

    1. USER user  
    2. USER user:group  
    3. USER uid  
    4. USER uid:gid  
    5. USER user:gid  
    6. USER uid:group

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

    ③RUN

    在所基于的镜像上执行命令,并提交到新的镜像中;分为

    在 shell 终端中运行命令,如 /bin/sh -c;

    使用 exec 执行,如RUN [“/bin/bash”, “-c”, “echo $HOME”]

    1. shell
    2. RUN <command>
    3. exec
    4. RUN ["executable","param1","param2"]

    ④CMD和ENTRYPOINT

    CMD

    指定启动容器时执行的命令,每个 Dockerfile 只能有一条 CMD 命令。如果指定了多条命令,只有最后一条会被执行。如果用户启动容器时候指定了运行的命令(如/bin/bash),则会覆盖掉 CMD 指定的命令

    1. CMD ["executable","param1","param2"] (执行可执行文件,优先)
    2. CMD ["param1","param2"] (设置了ENTRYPOINT,则直接调用ENTRYPOINT添加参数)
    3. CMD command param1 param2 (执行shell内部命令)

    ENTRYPOINT

    配置容器启动后执行的命令,并且不可被 docker run 提供的参数覆盖。
    每个 Dockerfile 中只能有一个 ENTRYPOINT,当指定多个时,只有最后一个起效

    1. ENTRYPOINT ["executable", "param1", "param2"]
    2. #(可执行文件, 优先)
    3. ENTRYPOINT command param1 param2
    4. #(shell内部命令)

    4.1CMD、ENTRYPOINT

    cmd 是容器环境启动时默认加载的命令 entrypoint 是容器环境启动时第一个加载的命令程序/脚本程序 init  

    如果 ENTRYPOINT 使用了 exec 模式,CMD 指定的内容被追加为 ENTRYPOINT 指定命令的参数。 如果 ENTRYPOINT 使用了 exec 模式,CMD 也应该使用 exec 模式;如果 ENTRYPOINT 使用了 shell 模式,CMD 指令会被忽略

    ⑤EXPOSE

    容器暴露的端口号,供互联系统使用。在启动容器时需要通过 -P,Docker 主机会自动分配一个端口转发到指定的端口。

     EXPOSE  [...]

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

    如果没有暴露端口,后期也可以通过-p 8080:80方式映射端口,但是不能通过-P形式映射

    ⑥ENV

    指定一个环境变量,会被后续 RUN 指令使用,并在容器运行时保持。

    1. ENV
    2. #之后的所有内容均会被视为其的组成部分,因此,一次只能设置一个变量
    3. ENV =...
    4. #可以设置多个变量,每个变量为一个"="的键值对,如果中包含空格,可以使用\来
    5. #进行转义,也可以通过""来进行标示;另外,反斜线也可以用于续行
    6. 例:
    7. ENV myname ljp
    8. ENV myname ljp ljp2
    9. ENV myname=ljp

    ⑦ADD和COPY

    ADD

    该命令将复制指定的src到容器中的 。 可以是Dockerfile所在目录的一个相对路径;也可以是一个 URL;还可以是一个 tar 文件(并自动解压为目录)

    1. ADD ...
    2. ADD ["",... ""]
    3. #用于支持包含空格的路径
    4. 例:
    5. ADD nginx-1.22.0.tar.gz Test/

    COPY

    复制本地主机的 (为 Dockerfile 所在目录的相对路径)到容器中的 。当使用本地目录为源目录时,推荐使用 COPY。

    ⑧VOLUME

    相当于运行容器时的-v

    创建一个可以从本地主机或其他容器挂载的挂载点,一般用来存放数据库和需要保持的数据等

    1. VOLUME /path /dir
    2. 例:
    3. VOLUME /log/messages /container/logs

    卷可以容器间共享和重用

    修改卷后会立即生效

    对卷的修改不会对镜像产生影响

    卷会一直存在,直到没有任何容器在使用它

    ⑨WORKDIR

    为后续的 RUN、CMD、ENTRYPOINT 指令配置工作目录。
    可以使用多个 WORKDIR 指令,后续命令如果参数是相对路径,则会基于之前命令指定的路径

    如第一次WORKDIR /test,此时工作目录为/test

    第二次WORKDIR test1,此时工作目录为/test/test1/

    在使用docker run运行容器时,可以通过-w参数覆盖构建时所设置的工作目录。

    WORKDIR /path/to/workdir

    三、dockerfile构建一个Tomcat镜像

    1. mkdir /mysql
    2. mv mysql-5.7.22-linux-glibc2.12-x86_64.tar.gz /mysql/
    3. mv mysql_data.tar.gz /mysql/

    ①编写dockerfile

    1. FROM centos:7
    2. MAINTAINER paullyu@foxmail.com
    3. ADD apache-tomcat-9.0.16.tar.gz /usr/local
    4. COPY jdk-8u201-linux-x64.rpm /usr/local
    5. WORKDIR /usr/local
    6. RUN mv apache-tomcat-9.0.16 tomcat && rpm -ivh jdk-8u201-linux-x64.rpm
    7. ENV JAVA_HOME /usr/java/jdk1.8.0_201-amd64
    8. ENV CLASS_PATH $JAVA_HOME/lib/tools.jar:$JAVA_HOME/lib/dt.jar
    9. ENV PATH $JAVA_HOME/bin:$PATH
    10. EXPOSE 8080
    11. CMD ["/usr/local/tomcat/bin/catalina.sh","run"]

    基础镜像centos:7,维护者信息

    解压缩tomcat的tar包到/use/local,复制jdk的rpm包进/usr/local

    定义工作目录 /usr/local,tomcat解压后目录改名,rpm安装jdk

    指定JAVA变量

    EXPOSE端口号8080

    容器运行命令,开启tomcat

    ②创建镜像并运行

    创建镜像

    1. [root@ljp tomcat]# ls
    2. apache-tomcat-9.0.16.tar.gz dockerfile jdk-8u201-linux-x64.rpm
    3. [root@ljp tomcat]# docker build -t tomcat:test

    基于创建的镜像运行容器 

    1. docker run -itd --name tomcat -p 9090:8080 tomcat:test
    2. netstat -natp | grep 9090
    3. tcp 0 0 0.0.0.0:9090 0.0.0.0:* LISTEN 16701/docker-proxy
    4. tcp6 0 0 :::9090 :::* LISTEN 16707/docker-proxy
    5. docker ps -a

    ③网页浏览tomcat

    http://192.168.116.22:9090

     

     

  • 相关阅读:
    构建高效的广告投放系统:应用架构的设计与实现
    JavaWeb的基本概念
    【思维构造】Dominant Character—CF1605C
    JDBC数据库的连接
    【教3妹学编程-算法题】最大异或乘积
    2024年区块链链游即将迎来大爆发
    【OpenCV实现图像:使用OpenCV进行物体轮廓排序】
    【转】ubuntu 安装 OpenCv 4.6脚本 installOCV.sh
    SpringMVC原理学习(二)参数解析器
    two ways to customize unordered_set
  • 原文地址:https://blog.csdn.net/m0_71518373/article/details/127389220