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 镜像:
我们也可以通过上一篇文章讲解的命令查看镜像层结构:
docker inspect 镜像id
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/
再次访问首页:
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 命令:
也就是说 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 命令都无法使用。
于是我们就编写一个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 登录阿里云
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
docker run -p 8082:8080 -it --name tomcat02 4b8ea0a44f9a /bin/bash
Docker从入门到精通(五)——Dockerfile的更多相关文章
- Python运算符,python入门到精通[五]
运算符用于执行程序代码运算,会针对一个以上操作数项目来进行运算.例如:2+3,其操作数是2和3,而运算符则是“+”.在计算器语言中运算符大致可以分为5种类型:算术运算符.连接运算符.关系运算符.赋值运 ...
- docker 从入门到精通
转载请注明出处!!!! 1.Docker 基本指令 下载镜像 docker pull 镜像名称:版本 查看已有镜像 docker images 查看已有容器 docker ps 启动docker do ...
- MyBatis从入门到精通(五):MyBatis 注解方式的基本用法
最近在读刘增辉老师所著的<MyBatis从入门到精通>一书,很有收获,于是将自己学习的过程以博客形式输出,如有错误,欢迎指正,如帮助到你,不胜荣幸! 1. @Select 注解 1.1 使 ...
- docker从入门到精通再到放弃
docker说明 docker三大功能:构建(build).运输(ship).运行(run),只需要记下这三大功能就可以了 1.docker入门 docker安装及配置 a.docker源配置 cur ...
- 《OD Docker实战》Docker从入门到精通
一. 安装Docker http://wiki.jikexueyuan.com/project/docker-technology-and-combat/ https://mos.meituan.co ...
- Docker从入门到精通(六)——容器通信
想要变成 Docker 的高阶玩家,搞懂 Docker 的容器通信是必不可少的. 1.需求 通常一个 Web 项目上线,我们会把开发完成的服务部署在Tomcat 服务器里面,然后需要的持久化数据会存放 ...
- Docker从入门到精通(八)——Docker Compose
恭喜大家,学到这里,对于 docker 的基础玩法大家应该都会了,下面会介绍 docker的一些编排工具. 1.为什么需要 Docker Compose? 官网镇楼:https://www.runoo ...
- Docker从入门到精通
1 容器简介1.1 什么是 Linux 容器1.2 容器不就是虚拟化吗1.3 容器发展简史2 什么是 Docker?2.1 Docker 如何工作?2.2 Docker 技术是否与传统的 Linux ...
- Docker从入门到精通(一)——初识
1.Docker 是什么? Docker 是一个开源的应用容器引擎,基于 Go 语言 并遵从 Apache2.0 协议开源. Docker 可以让开发者打包他们的应用以及依赖包到一个轻量级.可移植的容 ...
随机推荐
- 分布式链路追踪之Spring Cloud Sleuth+Zipkin最全教程!
大家好,我是不才陈某~ 这是<Spring Cloud 进阶>第九篇文章,往期文章如下: 五十五张图告诉你微服务的灵魂摆渡者Nacos究竟有多强? openFeign夺命连环9问,这谁受得 ...
- OWASP-Top5-(Security Misconfiguration 安全配置错误)
概述 从上一版的第 6 位开始,90% 的应用程序都经过了某种形式的错误配置测试.随着更多转向高度可配置的软件,看到这一类别上升也就不足为奇了.值得注意的CWE包括CWE-16 Configurati ...
- [atAGC050B]Three Coins
记$p_{i}$表示该位置是否有硬币 称使得$p_{i,i+1,i+2}$都变为1的操为对$i$的添加操作,使得$p_{i,i+1,i+2}$都变为0的操作为对$i$的删除操作 考虑一个简单的操作:若 ...
- [nowcoder5668I]Sorting the Array
令$f(n,b,m)=a[1..n]$(这里下标从1开始),考虑一些性质: 性质1.对于$\forall 1\le i\le n-m+1$,若$\exists 1\le j<i,a[j]> ...
- Codeforces 718E - Matvey's Birthday(思维题)
Codeforces 题面传送门 & 洛谷题面传送门 首先注意到这个图的特殊性:我们对于所有 \(s_i=s_j\) 的 \((i,j)\) 之间都连了条边,而字符集大小顶多只有 \(8\ ...
- 洛谷 P5299 - [PKUWC2018]Slay the Spire(组合数学+dp)
题面传送门 hot tea 啊--这种风格及难度的题放在省选 D2T1 左右还是挺喜闻乐见的罢 首先考虑对于固定的 \(m\) 张牌怎样求出最优的打牌策略,假设我们抽到了 \(p\) 张强化牌,攻击力 ...
- 对 SAM 和 PAM 的一点理解
感觉自己学 SAM 的时候总有一种似懂非懂.云里雾里.囫囵吞枣.不求甚解的感觉,是时候来加深一下对确定性有限状态自动机的理解了. 从 SAM 的定义上理解:SAM 可以看作一种加强版的 Trie,它可 ...
- python17进程
import os import time from multiprocessing.dummy import Process def so_sth(name): print("进程名称{} ...
- linux 线程函数小结
由于主线程已经开始跑了,次线程还在使用串口打印需要一点时间,因此打印的都是重复的. #include "pthread.h" #include "stdio.h" ...
- xmake v2.6.1 发布,使用 Lua5.4 运行时,Rust 和 C++ 混合编译支持
xmake 是一个基于 Lua 的轻量级跨平台构建工具,使用 xmake.lua 维护项目构建,相比 makefile/CMakeLists.txt,配置语法更加简洁直观,对新手非常友好,短时间内就能 ...