Dockerfile是为快速构建docker image而设计的,当你使用dockerbuild 命令的时候,docker 会读取当前目录下的命名为Dockerfile(首字母大写)的纯文本文件并执行里面的指令构建出一个docker image。这比SaltStack的配置管理要简单的多,不过还是要掌握一些简单的指令。
Dockerfile 由一行行命令语句组成,并且支持以#开头的注释行。指令是不区分大小写的,但是通常我们都大写。
 
下面我们通过构建一个Nginx的镜像来学习Dockerfile
 

Nginx Dockerfile实战

注意:第一个指令必须是FROM。

为了大家更容易学习,我这里总结一个命令的介绍:
一般的,我们将Dockerfile 分为四部分:
  • 基础镜像信息
  • 维护者信息
  • 镜像操作指令
  • 容器启动时执行指令
 
这就是学会Dockerfile的一张图

上图最后一个RUN应该为CMD

一. 构建Dockerfile

注意:ADD index.html就是放一个文件进去,这个文件需要大家自己准备一下。例如:
[root@linux-node1 mynginx]# echo “nginx indocker test” > index.html
使用dokcer build命令构建镜像
 [root@linux-node1mynginx]# docker build -t mynginx:v2 .
构建完毕之后,我们就可以Run起来。
[root@linux-node1 ~]# docker run -d -p92:80 nginx:v2 nginx
 

二. Dockerfile指令详解

 

1. FROM

格式:FROM<image>或FROM<image>:<tag>。
解释:FROM是Dockerfile里的第一条指令(必须是),后面跟有效的镜像名(如果该镜像你的本地仓库没有则会从远程仓库Pull取)。然后后面的其它指令FROM的镜像中执行。
 
 

2. MAINTAINER

格式:MAINTAINER <name>
解释:指定维护者信息。
 
 

3. RUN:在镜像构建过程中运行。

 
格式:RUN <command>或 RUN[“executable”, “param1”, “param2”](exec模式)
 解释:运行命令,命令较长使可以使用\来换行。推荐使用上面数组的格式
 
 例如: shell模式:RUN echo hello 执行的方式是用shell来执行,实际效果是 /bin/sh -c echo hello
          
            exec模式:可以指定其他形式的shell来执行指令
            RUN ["/bin/bash", "-c", "echo hello"]
           
两条RUN指令可以合并成一条, 例如:RUN apt-get update && apt-get -y nginx
 
docker build -t="镜像名" .   在当前目录构建镜像,注意后面的 点 表示当前目录
 
 

4. CMD:指定容器启动时的默认行为

格式:
CMD [“executable”,”param1″,”param2″] 使用 exec 执行,推荐方式;
CMD command param1 param2 在 /bin/sh 中执行,提供给需要交互的应用;
CMD [“param1″,”param2”] 提供给ENTRYPOINT的默认参数,和ENTRYPOINT搭配使用
 
解释:
CMD指定容器启动时执行的命令,每个Dockerfile只能有一条CMD命令,如果指定了多条,只有最后一条会被执行。如果你在启动容器的时候也指定的命令,那么会覆盖Dockerfile构建的镜像里面的CMD命令。
 
例如:使用exec方式
在dockerfile中添加 CMD ["/usr/sbin/nginx", "-g",  "daemon off;"]  启动容器时运行nginx, 并且以前台方式运行。
 
这样使用命令docker build -t="home/hong"(给镜像起名) .  构建一个home/hong的镜像后,
启动容器:docker run -d -p 80 --name cmd_test1 home/hong ---------不用再写容器启动的命令nginx -g "daemon off;")
 
之前不加CMD时,
启动容器:docker run -p 80 -d home/hong nginx -g "daemon off;"
 
如果使用命令docker run -d -p 80 --name cmd_test2 home/hong /bin/bash来启动一个容器,
再用docker ps -l 查看(显示最后一次创建的容器,包括未运行的),发现COMMAND列显示的内容已经变化为/bin/bash, 之前是/usr/sbin/nginx -g 
 
可以用docker top cmd_test1来查看容器的进程。
 
 

5. ENTRYPOINT

格式:
 
ENTRYPOINT [“executable”, “param1″,”param2”]
 
ENTRYPOINT command param1 param2(shell中执行)。
 
例如:ENTRYPOINT ["/usr/sbin/nginx", "-g",  "daemon off;"]
 
解释:和CMD类似,区别:不可被 docker run 提供的参数覆盖。
每个 Dockerfile 中只能有一个 ENTRYPOINT,当指定多个时,只有最后一个起效。ENTRYPOINT没有CMD的可替换特性,也就是你启动容器的时候增加运行的命令不会覆盖ENTRYPOINT指定的命令。
 
所以生产实践中我们可以同时使用ENTRYPOINT和CMD,使用ENTRYPOINT来指定命令,用CMD来指定命令默认的参数。
例如在dockerfile中写入如下命令来构建镜像后:
ENTRYPOINT ["/usr/sbin/nginx"]
CMD ["-h"]
 
启动容器:docker run -d -p 80 --name ep_test1 home/hong -g "daemon off"  
使用docker ps查看,显示的COMMAND参数为 /usr/sbin/nginx -g,表示CMD的默认参数被-g参数覆盖了
 
 
 

6.  USER --这个用户不会自动创建

 
格式:USER daemon
例如:USER user                    USER uid
         USER user:group          USER uid:gid
         USER user:gid               USER uid:group
 
解释:指定运行容器时的用户名和UID,后续的RUN指令也会使用这里指定的用户,默认会使用root用户
 
 

7. EXPOSE

 
格式:EXPOSE<port> [<port>…]   :指定运行该镜像的容器使用的端口,只是告诉别人我要用某个端口,但是并不会自动打开此端口,所以启动容器是还需要用参数-p或者-P来指定开启的端口号
 
例如:dockerfile中 EXPOSE 80
 
在容器运行时 docker run -p 80 -d home/hong nginx -g "daemon off;"
 
 
 

8. ENV

 
格式:ENV<key> <value>
          ENV <key>=<value> …
解释:设置环境变量,可以在RUN之前使用,然后RUN命令时调用,容器启动时这些环境变量都会被指定
 
 

9. ADD

格式:
ADD <src>… <dest>
ADD [“<src>”,… “<dest>”]
 
例子: ADD index.html /usr/share/nginx/html/  使用本地编写的网页,替换nginx的默认页面
 
解释:将指定的<src>复制到容器文件系统中的<dest>,
1. 一般来说src地址为本机dockerfile所在的目录,目标路径要使用容器中的绝对路径,
2. 所有拷贝到container中的文件和文件夹权限为0755,uid和gid为0
3. 如果文件是可识别的压缩格式,则docker会帮忙解压缩,还有一个COPY指令,和ADD用法完全一样,只是没解压缩功能,如果是纯拷贝,使用COPY好。
 
 

10. VOLUME

格式:VOLUME [“/data”]
解释:可以将本地文件夹或者其他container的文件夹挂载到container中。
 
 

11. WORKDIR:容器内部设置工作目录

格式:WORKDIR/path/to/workdir
解释:切换目录,为后续的RUN、CMD、ENTRYPOINT 指令配置工作目录。
可以多次切换(相当于cd命令),
 
也可以使用多个WORKDIR 指令,后续命令如果参数是相对路径,则会基于之前命令指定的路径。例如                 
WORKDIR /a
WORKDIR b
WORKDIR c
RUN pwd
 
则最终路径为 /a/b/c。
 
 
 

12. ONBUILD:为镜像添加触发器

 
ONBUILD 指定的命令在构建镜像时并不执行, 而是在它的子镜像中执行;
只有当一个镜像被其他镜像作为基础镜像时才会执行,会在构建过程中插入指令
 
例子,dockerfile文件如下
FROM ubuntu:14.04
RUN apt-get update
RUN apt-get install -y nginx
ONBUILD COPY index.html /usr/share/nginx/html/ #使用本地编写的网页,替换nginx的默认页面
EXPOSE 80
ENTRYPOINT ["/usr/sbin/nginx","-g",daemon off;"]
构建此镜像 docker build -t "home/hong" .   
 
然后按此镜像运行容器docker run -d -p 80 --name test0 home/hong
curl http://127.0.0.1:49169来查看页面,发现默认页面并没有改变
 
再写一个dockerfile文件
FROM home/hong
EXPOSE 80
ENTRYPOINT ["/usr/sbin/nginx","-g",daemon off;"]
再构建镜像docker build -t "test 1" .    在构建过程中发现触发了ONBUILD指令。
 
 

13. ARG

格式:ARG<name>[=<default value>]
 
解释:ARG指定了一个变量在docker build的时候使用,可以使用–build-arg <varname>=<value>来指定参数的值,不过如果构建的时候不指定就会报错。
 
 
 
 
 

一张图学dockerfile的更多相关文章

  1. (转)一张图学会Dockerfile

    原文:http://blog.51cto.com/kusorz/1942816 前言 Dockerfile是非常容易学的,和SHELL相比那简单的太多了. Dockerfile是为快速构建docker ...

  2. 八张图学通JavaScript 转自52

  3. 开局一张图,学一学项目管理神器Maven!

    Maven强大的Java工程构建工具,做Java开发时少了跟Maven打交道,之前在知乎上看到有人提问:"学Java开发需不需要学习Maven?",个人认为是必需要学的,这和工欲善 ...

  4. Nodejs学习笔记(三)——一张图看懂Nodejs建站

    前言:一条线,竖着放,如果做不到精进至深,那就旋转90°,至少也图个幅度宽广. 通俗解释上面的胡言乱语:还没学会爬,就学起走了?! 继上篇<Nodejs学习笔记(二)——Eclipse中运行调试 ...

  5. 几张图帮你理解 docker 基本原理及快速入门

    写的非常好的一篇文章,不知道为什么被删除了.  利用Google快照,做个存档. 快照地址:地址 作者地址:青牛 什么是docker Docker 是一个开源项目,诞生于 2013 年初,最初是 do ...

  6. 一张图搞清楚PMBOK所有过程的使用

      很多参加PMP培训的学员大概都会有一个感受,上课时似乎每个知识点都听懂了,大的知识框架也弄明白了,但是所有这些串起来在实践中怎么用呀!说的再直接一点,在考试的时候这些过程和活动是以怎样的逻辑来应用 ...

  7. 一张图入门Python【中文版】

    好久没写了,就拿这张图作为开篇吧,重新梳理自己学习的东西,最近两年人工智能炒红了python,devops的提出也把开发.运维整合到了一起,作为一个运维工程师,随着企业自动化运维的提出,光会shell ...

  8. 想了解Java后端学习路线?你只需要这一张图!

    前言 学习路线图往往是学习一样技术的入门指南.网上搜到的Java学习路线图也是一抓一大把. 今天我只选一张图,仅此一图,足以包罗Java后端技术的知识点.所谓不求最好,但求最全,学习Java后端的同学 ...

  9. 面试问了解Linux内存管理吗?10张图给你安排的明明白白!

    文章每周持续更新,各位的「三连」是对我最大的肯定.可以微信搜索公众号「 后端技术学堂 」第一时间阅读(一般比博客早更新一到两篇) 今天来带大家研究一下Linux内存管理.对于精通 CURD 的业务同学 ...

随机推荐

  1. Visual C++中去除警告

    在编程中,编译器警告的意思是提问程序员:如果这样做将会出现意外的错误,你确定要这样做吗? 在很多情况下,我们写程序的时候会出现一些警告,而这些警告我们都知道这样做的确是需要的并且程序中多处出现这种做法 ...

  2. 游戏服务器学习笔记 4———— master 模块介绍

    (模块的介绍方法都是先说大体功能,在捡一些细节详细讨论.) master 类很简单,就3个函数,一个init,设置配置信息,并调用masterapp,然后还有一个循环启动子进程的start函数. 这里 ...

  3. c++ map使用问题【运行结果不一样】

    map经常把指针作为key,这种情况下. 我们经常会很自然的以为,如果要取元素时,会按照我们存的顺序拿到元素. 但是事实上不是这样的,因为map取得时候是按key的大小排序的,而如果用指针作为key, ...

  4. VC++生成不同的随机数

    其用法是先调用srand函数,如 srand( (unsigned)time( NULL ) ) 这样可以使得每次产生的随机数序列不同.假如计算伪随机序列的初始数值(称为种子)相同,则计算出来的伪随机 ...

  5. 使用TELNET手工操作 IMAP 查看邮件

    http://www.cnblogs.com/CrazyWill/archive/2006/08/12/474884.html IMAP 协议收信与POP收信有很大的不同,最明显的一点就是发送的每条命 ...

  6. sencha touch 类的使用

    sencha touch 有一套自己的类机制,可以以面向对象的方式去写代码,封装业务逻辑,sencha touch 的组件.插件.api等都建立在这一套类机制的上面 在实际开发中,我们需要遵循这一套机 ...

  7. sencha touch 隐藏滚动条样式的几种方式

    如图,当滚动条显示时不是那么的好看   可以通过以下几种方式来隐藏滚动条,而又不影响滚动效果 1.通过css隐藏 /* 隐藏x方向滚动条 */ .x-scroll-bar-x.active { wid ...

  8. nginx命令行参数和信号

    nginx命令行参数 [user@host dir]$ /usr/local/nginx/sbin/nginx -hnginx version: nginx/1.8.0Usage: nginx [-? ...

  9. SSH用户枚举漏洞(CVE-2018-15473)原理学习

    一.漏洞简介 1.漏洞编号和类型 CVE-2018-15473 SSH 用户名(USERNAME)暴力枚举漏洞 2.漏洞影响范围 OpenSSH 7.7及其以前版本 3.漏洞利用方式 由于SSH本身的 ...

  10. csdn博客刷点击率(java代码)

    此文为转载,亲测有效. import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; impo ...