使用Dockerfile定制镜像
Dockerfile是一个文本文件,其中包含额一条一条的指令,每一条指令构建一层,因此每一条指令的作用就是描述这一层应当如何的构建。
以构建nginx镜像为例,使用Dockerfile构建的步骤如下:
在一个空的目录下创建一个名为Dockerfile的文件:
sudo mkdir mynginx
cd mynginx
sudo touch Dockerfile
编辑Dockerfile文件,内容如下:
FROM nginx
RUN echo '<h1>hello,Docker!</h1>' > /usr/share/nginx/html/index.html
上述的Dockerfile文件很简单,只有两个步骤,涉及到两个指令:FROM和RUN
FROM指定基础镜像
所谓的定制镜像,就是以一个镜像为基础,在其上进行定制。而FROM指令的作用就是指定基础镜像,因此在一个Dockerfile文件中FROM指令是必须存在的,并且必须是第一条指令。
在 Docker Store 上有非常多的高质量的官方镜像,有可以直接拿来使用的服务类的镜像,如
nginx 、 redis 、 mongo 、 mysql 、 httpd 、 php 、 tomcat 等;也有一些方便开发、构建、运行各种语言应用的镜像,如 node 、 openjdk 、 python 、 ruby 、 golang 等。可以在其中寻找一个最符合我们最终目标的镜像为基础镜像进行定制。
如果没有找到对应服务的镜像,官方镜像中还提供了一些更为基础的操作系统镜像,如
ubuntu 、 debian 、 centos 、 fedora 、 alpine 等,这些操作系统的软件库为我们提供了更广阔的扩展空间。
除了选择现有镜像为基础镜像外,Docker 还存在一个特殊的镜像,名为 scratch 。这个镜像
是虚拟的概念,并不实际存在,它表示一个空白的镜像。如果你以 scratch 为基础镜像的话,意味着你不以任何镜像为基础,接下来所写的指令将作为镜像第一层开始存在。
RUN执行命令
RUN 指令是用来执行命令行命令的。由于命令行的强大能力, RUN 指令在定制镜像时是最
常用的指令之一。其格式有两种:
- shell 格式: RUN <命令> ,就像直接在命令行中输入的命令一样。刚才写的 Dockerfile 中的 RUN 指令就是这种格式。
- exec 格式: RUN ["可执行文件", "参数1", "参数2"] ,这更像是函数调用中的格式
既然RUN就像SHELL脚本一样可以执行命令,那么我们能否向SHELL脚本那样把每条命令对应一个RUN呢?比如一下这样:
FROM debian:jessie
RUN sudo apt-get update
RUN sudo apt-get install -y gcc libc6-dev make
RUN sudo wget -O redis.tar.gz "http://download.redis.io/releases/redis-3.2.5.tar.gz"
RUN sudo mkdir -p /usr/src/redis
RUN sudo tar -xzf redis.tar.gz -C /usr/src/redis --strip-components=1
RUN sudo make -C /usr/src/redis
RUN sudo make -C /usr/src/redis install
之前说过Dockerfile的每条指令对应一层,RUN也一样,每一个RUN的行为建立一个新的层,在其上执行这些命令,执行结束后, commit 这一层的修改,构成新的镜像。而上面的写法创建了7层镜像,这是完全没有意义的,很多运行时候不需要的东西被封进了镜像,比如更新的软件包和编译环境。这样产生的镜像就很臃肿,容易出错。
Union FS是有最大层数限制的,不得超过127层,上面的Dockerfile的正确的写法如下:
FROM debian:jessie
RUN buildDeps='gcc libc6-dev make' \
&& apt-get update \
&& apt-get install -y $buildDeps \
&& wget -O redis.tar.gz "http://download.redis.io/releases/redis-3.2.5.tar.gz" \
&& mkdir -p /usr/src/redis \
&& tar -xzf redis.tar.gz -C /usr/src/redis --strip-components=1 \
&& make -C /usr/src/redis \
&& make -C /usr/src/redis install \
&& rm -rf /var/lib/apt/lists/* \
&& rm redis.tar.gz \
&& rm -r /usr/src/redis \
&& apt-get purge -y --auto-remove $buildDeps
这里使用&&将多个指令链接起来,将原来的7层简化为1层。在撰写 Dockerfile 的时候,要经常提醒自己,这并不是在写 Shell 脚本,而是在定义每一层该如何构建。这一组命令的最后添加了清理工作的命令,删除了为了编译构建所需要的软件,清理了所有下载、展开的文件,并且还清理了 apt 缓存文件。这是很重要的一步,我们之前说过,镜像是多层存储,每一层的东西并不会在下一层被删除,会一直跟随着镜像。因此镜像构建时,一定要确保每一层只添加真正需要添加的东西,任何无关的东西都应该清理掉。
构建镜像
构建镜像可以使用docker build命令,命令格式如下:
docker build [选项] <上下文路径/URL/->
让我们来构建之前nginx的定制镜像,进入到Dockerfile所在的目录,执行一下命令:
sudo docker build -t nginx:v3 .
Sending build context to Docker daemon 2.048 kB
Step 1 : FROM nginx
---> e43d811ce2f4
Step 2 : RUN echo '<h1>Hello, Docker!</h1>' > /usr/share/nginx/html/index.html
---> Running in 9cdc27646c7b
---> 44aa4490ce2c
Removing intermediate container 9cdc27646c7b
Successfully built 44aa4490ce2c
从命令的输出结果中,我们可以清晰的看到镜像的构建过程。在 Step 2 中,如同我们之前所说的那样, RUN 指令启动了一个容器 9cdc27646c7b ,执行了所要求的命令,并最后提交了这一层 44aa4490ce2c ,随后删除了所用到的这个容器 9cdc27646c7b。
未完待续
使用Dockerfile定制镜像的更多相关文章
- 利用dockerfile定制镜像
利用dockerfile定制镜像 镜像的定制就是定制每一层所添加的配置.文件.如果可以吧每一层修改.安装.构建.操作的命令都写入到一个脚本,用脚本来构建.定制镜像,这个脚本就是dockerfile. ...
- Dockerfile定制镜像
一.Dockerfile是什么? 镜像定制实质就是定制每一层所添加的配置.文件. Dockerfile就是一个脚本来构建和定制镜像,把每一层的修改.安装.构建.操作都写入脚本.以此来解决体积.镜像构建 ...
- 微服务架构 ------ Dockerfile定制镜像
Docker容器不仅仅是运行原生的容器,而是把我们的具体的项目能够布置到容器上面去,这就是Docker定制镜像需要做的事情. Docker容器 = new Docker镜像 镜像相当于类,容器相当 ...
- Docker 学习笔记(二):Dockerfile 定制镜像
镜像的定制实际上就是定制每一层所添加的配置.文件. 如果我们可以把每一层修改.安装.构建.操作的命令都写入一个脚本,用这个脚本来构建.定制镜像,那么之前提及的无法重复的问题.镜像构建透明性的问题.体积 ...
- Docker Dockerfile 定制镜像
使用 Dockerfile 定制镜像 镜像的定制实际上就是定制每一层所添加的配置.文件.如果我们可以把每一层修改.安装.构建.操作的命令都写入一个脚本,用这个脚本来构建.定制镜像,那么无法重复的问题 ...
- Docker用Dockerfile定制镜像
用Dockerfile定制镜像 镜像的定制实际上就是定制每一层所添加的配置.文件.如果我们可以把每一层修改.安装.构建.操作的命令都写入一个脚本,用这个脚本来构建.定制镜像,那之前提示的无法重复的问题 ...
- Docker Dockerfile 定制镜像(转)
转自: https://yeasy.gitbooks.io/docker_practice/ 及 https://blog.csdn.net/wo18237095579/article/details ...
- Dockerfile 定制镜像
从上一篇文章中我们可以了解到,镜像的定制实际上就是定制每一层所添加的配置.文件等信息,但是命令毕竟只是命令,每次定制都得去重复执行这个命令,而且还不够直观,如果我们可以把每一层修改.安装.构建.操作的 ...
- 利用 Dockerfile 定制镜像
镜像的定制实际上就是定制每一层所添加的配置.文件. 如果我们可以把每一层修改.安装.构建.操作的命令都写入一个脚本,用这个脚本来构建.定制镜像, 那么之前提及的无法重复的问题.镜像构建透明性的问题.体 ...
随机推荐
- json.dumps错误:'utf8' codec can't decode byte解决方案-乾颐堂
一次在使用json.dumps()过程中,出现错误提示: ERROR:"UnicodeDecodeError: 'utf8' codec can't decode byte 0xe1 in ...
- TLS/SSL简单过程
.wcf的认证分为两种 1.1 transport模式,在传输层完成认证(只能在传输层完成认证,利用硬件加速效率更高) a.在使用transport模式,非windows凭证的情况下默认使用TLS/S ...
- 构造函数constructor 与析构函数destructor(一)
构造函数定义:构造函数c++中在创建对象时自动调用,用来初始化对象的特殊函数. (1)构造函数的名字必须与类的名字相同,不能有返回值,哪怕是void 也不行. (2)通常情况下构造函数应声明为公有函数 ...
- 2018.09.11 poj2976Dropping tests(01分数规划)
传送门 01分数规划板子题啊. 就是简单变形移项就行了. 显然 ∑i=1na[i]∑i=1nb[i]≤k" role="presentation" style=" ...
- java常用设计模式一:单例模式
1.饿汉式 package singleton.demo; /** * @author Administrator * @date 2019/01/07 */ public class Single ...
- nlms_step_get
module nlms_step_get( rst , clk , nd , din01_i, din01_q, din02_i, din02_q, dou ...
- 状态机中的RAM注意的问题--减少扇出的办法
可能我不会抓紧时间,所以做事老是很慢.最近在整维特比译码过程深感自己有这样的毛病. 每天会有一点进展,但是却是一天的时间,感觉别人都做起事情来很快.可能这个东西有点难,做 不做得出来都不要紧,但我的想 ...
- Android中Activity启动过程探究
首先追溯到Activity的启动,随便启动一个自己写的demo项目,使用DDMS进行debug标记,然后在Debug中把主线程暂停,可以看到调用栈.如下图所示: 于是我们先看android.app.A ...
- OpenGL常用的函数
OpenGL常用的函数 1. void glBegin(GLenummode) void glEnd(void) 参数说明: mode:创建图元的类型.可以是以下数值 GL_POINTS:把每一个顶点 ...
- console的所有用法
http://jingyan.baidu.com/article/e75aca855c6419142edac6c1.html 参考它. console.info(), console.debug() ...