zoukankan      html  css  js  c++  java
  • Docker从入门到精通(五)——Dockerfile

    Dockerfile 简单来说就是一个包含用于组合镜像的命令的文本文档,Docker 通过读取 Dockerfile 中的指令就可以按步骤生成镜像,那么在制作镜像之前,我们先了解一下镜像的原理。

    1、镜像原理

    只有了解镜像的原理,我们才能更清晰的通过 Dockerfile 制作镜像。

    前面几篇文章我们简单介绍了docker中的镜像,镜像是只读的文件,提供了运行程序完整的软硬件资源,是应用程序的“集装箱”,包含运行某个软件所需的所有内容,包括代码、运行时环境、所需库、环境变量、配置文件等等。

    那么镜像是如何做到这些的呢?

    1.1 UnionFS(联合文件系统)

    联合文件系统(Union File System):2004 年由纽约州立大学开发,它可以把多个目录内容联合挂载到同一个目录下,而目录的物理位置是分开的。UnionFS可以把只读和可读写文件系统合并在一起,具有写时复制功能,允许只读文件系统的修改可以保存到可写文件系统当中。

    UnionFS(Union File System) 一次性加载多个文件系统,但是从外表看起来,只能看到一个文件系统,联合加载会把各层文件系统叠加起来,这样最终的文件系统会包含所有底层的文件和目录。

    1.2 Docker 镜像加载原理

    Docker 的镜像实际上就是由一层一层的文件系统组成,这里给出 Docker 官方的一张图:

    图片描述

    Bootfs(boot file system):主要包含 bootloader 和 kernel,bootloader 主要是引导加载 kernel,比如 Linux 刚启动时会加载 bootfs 文件系统,在 Docker 镜像的最底层就是 bootfs。这一层与我们典型的 Linux/Unix 系统是一样的,包含 boot 加载器和内核。当 boot 加载完成之后整个内核就都在内存中了,此时内存的使用权已由 bootfs 转交给内核,此时系统也会卸载 bootfs。

    Rootfs(root file system):在 bootfs 之上,中间只读的 rootfs 的集合称为 Docker 镜像,Docker 镜像构建时,会一层层构建,前一层是后一层的基础。每一层构建完就不会再发生改变,后一层上的任何改变只发生在自己这一层。UnionFS 使得镜像的复用、定制变得更为容易。甚至可以用之前构建好的镜像作为基础层,然后进一步添加新的层,以定制自己所需的内容,构建新的镜像。

    Container(容器):容器 = 镜像 + 读写层,从文件系统上看,Docker容器比Docker镜像多一层可读写的文件系统挂载层。借助于 UnionFS,容器内部的更改都被保存到了最上面的读写层,而其他层都是只读的,这样中间的只读 rootfs 是可以被多个容器复用的。UnionFS 将文件的更新挂载到老的文件之上,而不去修改那些不更新的内容,这就意味着即使虚拟的文件系统被反复修改,也能保证宿主机空间占用保持一个较低水平。

    在 rootfs 的基础上,Docker 公司创新性地提出了使用 UnionFS,多个增量 rootfs 联合挂载一个完整 rootfs 的方案,通过“分层镜像”的设计,围绕 Docker 镜像,大家甚至可以协同工作,再加上 Docker 官方提供的镜像仓库,进一步减少了共享镜像的成本,这大大提高了开发部署的效率。

    这样你也能理解为什么 docker 启动块,占用资源少了吧。

    1.3 实操理解分层概念

    这里我们下载一个 Tomcat9.0 镜像:

    image-20211031120617204

    我们也可以通过上一篇文章讲解的命令查看镜像层结构:

    docker inspect 镜像id

    image-20211031121152140

    2、Dockerfile 的 helloworld

    实例:创建一个能访问 Tomcat 首页的容器

    2.1 手动创建

    通常我们启动一个Tomcat容器,官方镜像是简化版的,在webapps 目录下没有任何内容,所有我们启动之后访问主页也是没有任何内容。

    docker run -d -p 8080:8080 tomcat

    但是官方镜像的 webapps.dist 目录下有首页文件,所以我们将 webapps.dist 目录下的所有文件复制到 webapps ,然后访问首页就有界面了。

    1、进入启动的容器

    docker exec -it 容器id /bin/bash

    2、将webapps.dist 目录所有文件复制到 webapps 目录下

    cp -r webapps.dist/* webapps/

    image-20211031135744274

    再次访问首页:

    2.2 Dockerfile 创建

    PS: 不同命令没关系,后面会解释每条命令含义。

    ①、提前准备好 webapps 目录文件

    我这里直接将官方Tomcat容器中的 webapps.dist 目录拷贝到本机的/home/webapps 目录下:

    docker cp 容器ID:/usr/local/tomcat/webapps.dist /home/webapps

    ②、准备 dockerfile 文件

    在本机 /home 目录下新建一个 Dockerfile 文件(可以任意命名,没有后缀),内容如下:

    FROM tomcat:latest
    MAINTAINER itcoke
    WORKDIR /usr/local/tomcat/webapps
    COPY ./webapps/ /usr/local/tomcat/webapps/
    

    ③、构建镜像

    docker build -f Dockerfile -t itcoke/mytomcat:1.0 .

    ④、运行镜像

    docker run -d -p 8081:8080 itcoke/mytomcat:1.0

    ⑤、访问首页测试

    可以看到如下图的首页界面,即构建运行成功。

    3、Dockerfile 指令详解

    在上面了我们编写了一个 Dockerfile 文件,内容如下:

    FROM tomcat:latest
    MAINTAINER itcoke
    WORKDIR /usr/local/tomcat/webapps
    COPY ./webapps/ /usr/local/tomcat/webapps/
    

    那这里面每条指令是什么意思呢?接下来我们揭开这层神秘的面纱。

    3.1 编写规范

    ①、每条指令(每行开头关键字)都必须是大写字母;

    ②、执行顺序是按照编写顺序从上到下;

    ③、# 表示注释;

    3.2 常用指令介绍

    ①、FROM

    FROM centos #依赖官方基准镜像(centos:lastest)

    FROM scratch #不依赖任何基准镜像

    FROM tomcat:9.0-jdk8-openjdk #指定具体版本号

    ②、MAINTAINER

    通常表示镜像来自哪个机构。类似还有比如 LABEL 标签,展示镜像的一些说明信息,不会对镜像有实际影响。

    LABEL version=“1.0”

    LABEL description="初版xxx服务"

    ③、WORKDIR

    WORKDIR 路径 # WORKDIR /usr/local

    指定工作目录,也是我们进入镜像的路径,如果指定路径不存在,该指令也会自动创建该目录。

    PS:尽量使用绝对路径,这样更加清晰。

    ④、ADD 和 COPY

    都是进行文件复制。

    ADD 功能更加强大一点,支持压缩包的解压,还支持远程文件的复制。

    ⑤、ENV

    设置环境常量。

    比如:

    ENV JAVA_HOME /usr/local/openjdk8

    RUN ${JAVA_HOME}/bin/java -jar test.jar

    尽量使用环境常量,这样可以提高程序的可维护性。

    3.3 RUN 和 CMD 和 ENTRYPOINT

    RUN: 在镜像构建时执行命令,比如 RUN yum -y install vim;

    ENTRYPOINT:容器启动时执行的命令;

    CMD:容器启动后执行默认的命令或参数;

    ①、RUN

    构建时运行,有两种命令格式:

    RUN yum install -y vim #Shell 命令格式

    RUN ["yum","install","-y","vim"] #Exec命令格式

    官方推荐使用 Exec 命令格式。

    ②、ENTRYPOINT

    容器启动时执行的命令。

    命令格式也是推荐使用 Exec。

    注意:Dockerfile 中只有最后一个 ENTRYPOINT 会被执行。

    ③、CMD

    用于设置默认执行的命令。

    和ENTRYPOINT 命令一样,也是只有最后一个 CMD 命令会被执行,但是如果容器启动时附加指令,则CMD会被忽略。

    CMD ["ps","-ef"] #推荐使用 Exec 格式。

    比如有如下Dockerfile 文件:

    构建,然后启动时(不附加命令),会输出 3:

    如果启动时附加命令,则会执行附加的命令(下图附加 ls 命令),而不执行Dockerfile 中的CMD 命令:

    image-20211104085058681

    也就是说 ENTRYPOINT 指令一定会执行,但是 CMD 指令不一定会执行。

    3.4 docker build 命令

    编写好的 Dockerfile 通过 docker build 构建镜像。

    docker build [OPTIONS] PATH | URL | -

    ①、-f:指定要使用的 Dockerfile 文件路径。

    ②、-t(-tag):镜像的名字和标签,通常是 name:tag。

    4、Dockerfile 构建 centos

    我们拉取官方的 centos 系统,发现是一个简化版的,常用的一些 vim 命令,ifconfig 命令都无法使用。

    image-20211101082327112

    于是我们就编写一个Dockerfilew 文件来构建一个自己的 centos系统,有两个要求:

    ①、安装好vim以及一些网络命令;

    ②、设置工作目录为 /usr/local;

    按照要求,我们在 /home 目录下新建 Dockerfile_MyCentos 文件,内容如下:

    FROM centos
    WORKDIR /usr/local
    RUN yum -y install vim
    RUN yum -y install net-tools
    EXPOSE 80
    CMD echo "install successful"
    CMD /bin/bash
    

    通过如下语句构建:

    docker build -f Dockerfile_MyCentos -t mycentos:1.0 .

    PS:对于构建命令,加入你新建的 Dockerfile 文件名称就是【Dockerfile】,那可以不加 -f 文件名 来指定,docker 会自动寻找。

    构建成功后,就生成了自己的镜像:

    我们运行这个镜像,发现这个centos 系统,vim,ifconfig 等网络命令都可以用了。

    5、推送镜像到阿里云

    上面我们镜像制作完成,如何推送到阿里云呢?

    5.1 登录阿里云

    https://cr.console.aliyun.com/cn-hangzhou/instances

    5.2 创建命名空间

    5.3 创建镜像仓库

    测试阶段选择本地仓库就行。

    5.4 推送操作指南

    点开创建的镜像仓库,就会看到详细的操作指南。

    看到第 3 点,将镜像推送到 Registry:

    docker login --username=182****5732 registry.cn-hangzhou.aliyuncs.com
    docker tag [ImageId] registry.cn-hangzhou.aliyuncs.com/itcoke/test:[镜像版本号]
    docker push registry.cn-hangzhou.aliyuncs.com/itcoke/test:[镜像版本号]
    

    第一条命令是登录阿里云,输入时需要在此输入密码,如果忘记密码了,可以到【访问凭证】里面重新设置。

    第二条是设置 tag:

    docker tag e10136600f85 registry.cn-hangzhou.aliyuncs.com/itcoke/test:1.0

    第三条命令是推送到阿里云:

    docker push registry.cn-hangzhou.aliyuncs.com/itcoke/test:1.0

    查看阿里云镜像版本,也能看到我们推送过去的镜像信息:

    点开【层信息】,里面的内容就是我们编写的 Dockerfile 相关信息。

    6、从阿里云pull镜像

    7、退出登录

    docker logout

    作者:IT可乐

    资源:微信搜【IT可乐】关注我,回复 【电子书】有我特别筛选的免费电子书。
    本文版权归作者所有,欢迎转载,但未经作者同意不能转载,否则保留追究法律责任的权利。
  • 相关阅读:
    算法导论 第一章
    20155312 2016-2017-2 《Java程序设计》第七周学习总结
    Visual Studio 2005 搭建Windows CE 6.0环境之准备
    C#在winform中调用系统控制台输出
    C# 目录(文件夹)复制实现
    关于加强数据库安全的一些实践
    运维小白部署网站踩坑全过程
    jQuery学习之二 jQuery选择器
    运维系列之二 Linux文件种类和扩展名
    运维系列之一 Linux的文件与目录权限解析
  • 原文地址:https://www.cnblogs.com/ysocean/p/15659105.html
Copyright © 2011-2022 走看看