本文原创,原文地址为:http://www.cnblogs.com/fengzheng/p/5181222.html

创建镜像的目的

首先说DockerHub或其它一些镜像仓库已经提供了够多的镜像,有最小版本,也有一些安装了mysql、nginx、apache等等第三方软件的版本可以直接拿来使用。虽然已经足够多了,但是有些情况下并不能满足我们的需求,例如需要安装一些比较少用到的第三方软件,这个时候只能先用公共仓库中的镜像,启动容器,然后在容器中按照我们的需求安装软件,修改配置等等操作,之后提交镜像。这些操作在之前的文章中介绍了。这样操作完成之后,可以用如下两种方式实现定制镜像的目的:

1.用save和export的方式将镜像保存为tar包,然后在需要的时候导入tar镜像包

2.将已经配置好的镜像push到我们的私有仓库(docker创建私有仓库)或者已注册过的共有仓库中,需要的时候直接pull下来使用

这两种方式都可以,但是自动化程度低、自由度不够、定制起来比较麻烦。既然如此,那就来说一下更加自动化的创建方式。

Dockerfile结构

dockerfile由4部分信息组成:基础镜像信息、维护者信息、镜像操作指令和容器启动时执行指令。

# This dockerfile uses the ubuntu image
# VERSION 2 - EDITION 1
# Author: docker_user
# Command format: Instruction [arguments / command] .. # Base image to use, this must be set as the first line
FROM ubuntu # Maintainer: docker_user <docker_user at email.com> (@docker_user)
MAINTAINER docker_user docker_user@email.com # Commands to update the image
RUN echo "deb http://archive.ubuntu.com/ubuntu/ raring main universe" >> /etc/apt/sources.list
RUN apt-get update && apt-get install -y nginx
RUN echo "\ndaemon off;" >> /etc/nginx/nginx.conf # Commands when creating a new container
CMD /usr/sbin/nginx

其中#表注释,可以标注一些说明性的文字。

FROM关键字指定镜像的来源,默认为DockerHub,也可以写私有仓库的镜像,例如:localhost:5000/centos:6.7,如果本地已经存在指定的镜像名称,则会从本地缓存直接获取。MAINTAINER 指定镜像的作者,之后为镜像操作执行RUN、ADD等,最后是容器启动时发起的指令。

Dockerfile中的指令

FROM: 指定镜像名称,格式为FROM <image> 或FROM <image>:<tag>,例如FROM ubuntu 或 FROM ubuntu:12.04 

MAINTAINER: 镜像作者 ,格式为 MAINTAINER <name>

RUN:格式为 RUN <command> 或 RUN ["executable", "param1", "param2"]

前者将在 shell 终端中运行命令,即 /bin/sh -c;后者则使用 exec 执行。指定使用其它终端可以通过第二种方式实现,例如 RUN ["/bin/bash", "-c", "echo hello"]

每条 RUN 指令将在当前镜像基础上执行指定命令,并提交为新的镜像。当命令较长时可以使用 \ 来换行。

CMD:支持三种格式

  1.CMD ["executable","param1","param2"] 使用 exec 执行,推荐方式;
  2.CMD command param1 param2 在 /bin/sh 中执行,提供给需要交互的应用;
  3.CMD ["param1","param2"] 提供给 ENTRYPOINT 的默认参数;
指定启动容器时执行的命令,每个 Dockerfile 只能有一条 CMD 命令。如果指定了多条命令,只有最后一条会被执行。如果用户启动容器时候指定了运行的命令,则会覆盖掉 CMD 指定的命令。

EXPOSE:格式为 EXPOSE <port> [<port>...]

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

ENV:格式为 ENV <key> <value>。 指定一个环境变量,会被后续 RUN 指令使用,并在容器运行时保持。这就对应程序语言中的变量定义,可在需要的时候引用。例如:

ENV PG_MAJOR 9.3
ENV PG_VERSION 9.3.4
RUN curl -SL http://example.com/postgres-$PG_VERSION.tar.xz | tar -xJC /usr/src/postgress && …
ENV PATH /usr/local/postgres-$PG_MAJOR/bin:$PATH

ADD:格式为 ADD <src> <dest>

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

COPY:格式为 COPY <src> <dest>

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

COPY和ADD的不同就是:ADD多了自动解压和支持URL路径的功能。

ENTRYPOINT:

两种格式:

  • ENTRYPOINT ["executable", "param1", "param2"]
  • ENTRYPOINT command param1 param2(shell中执行)。

配置容器启动后执行的命令,并且不可被 docker run 提供的参数覆盖。

每个 Dockerfile 中只能有一个 ENTRYPOINT,当指定多个时,只有最后一个起效。

CMD和ENTRYPOINT比较:两个命令都是只能使用一次,并且都是在执行docker run指令时运行,如果有多个,只执行最后一条。

两者的不同在于参数的传递方式,如果在Dockerfile中定义如下指令

CMD echo hello

ENTRYPOINT ["echo","hello"] 

那么在运行命令docker run containerId echo world时,指定了CMD的输入结果为world,可以看出Dockerfile中指定的命令被覆盖了,而指定了ENTRYPOINT时,输出结果为hello echo world,可以看出指定的命令被作为ENTRYPOINT指定指令的参数了。

VOLUME:格式为 VOLUME ["/data"]。创建一个可以从本地主机或其他容器挂载的挂载点,一般用来存放数据库和需要保持的数据等。不过此属性在Dockerfile中指定并没有什么意义,因为没有办法指定本地主机的目录。如果需要指定挂载点可以在执行docker run命令时指定:

docker run -it -v /home/fengzheng/ftp/:/data  859666d51c6d /bin/bash

USER:格式为 USER daemon。指定运行容器时的用户名或 UID,后续的 RUN 也会使用指定用户。

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

WORKDIR:格式为 WORKDIR /path/to/workdir。为后续的 RUNCMDENTRYPOINT 指令配置工作目录。可以使用多个 WORKDIR 指令,后续命令如果参数是相对路径,则会基于之前命令指定的路径。例如

WORKDIR /a
WORKDIR b
WORKDIR c
RUN pwd

则最终路径为 /a/b/c

ONBUILD:格式为 ONBUILD [INSTRUCTION]

配置当所创建的镜像作为其它新创建镜像的基础镜像时,所执行的操作指令。

例如,Dockerfile 使用如下的内容创建了镜像 image-A

[...]
ONBUILD ADD . /app/src
ONBUILD RUN /usr/local/bin/python-build --dir /app/src
[...]

如果基于 image-A 创建新的镜像时,新的Dockerfile中使用 FROM image-A指定基础镜像时,会自动执行ONBUILD 指令内容,等价于在后面添加了两条指令。

FROM image-A

#Automatically run the following
ADD . /app/src
RUN /usr/local/bin/python-build --dir /app/src

使用 ONBUILD 指令的镜像,推荐在标签中注明,例如 ruby:1.9-onbuild

基于CentOS6.7并源码安装nginx

首先准备了nginx-1.9.9.tar.gz安装包和CentOS6-Base-163.repo(163源),将这两个文件放到同一目录下,并在此目录下创建名称为Dockerfile的文件。之后在此文件中实现源替换、nginx编译安装、及一些依赖包的安装,Dockerfile内容如下:

# this is a test ubuntu 12.04 image dockerfile
# Author:fengzheng # Base image,this must be set as the first line
#localhost:5000/centos:6.7是我的私有仓库的镜像,可替换为centos:6.7(DockerHub中的镜像)
FROM localhost:5000/centos:6.7 MAINTAINER fengzheng # Commands to update the image RUN mkdir /usr/nginx1.9.9
ADD nginx-1.9.9.tar.gz /usr/nginx1.9.9/
#RUN yum -y install tar
#RUN tar -zxvf /usr/nginx1.9.9/nginx-1.9.9.tar.gz
RUN cd /etc/yum.repos.d/ && mv CentOS-Base.repo CentOS-Base.repo.bak
ADD CentOS6-Base-163.repo /etc/yum.repos.d/
RUN cd /etc/yum.repos.d/ && mv CentOS6-Base-163.repo CentOS-Base.repo \
&& yum clean all && yum makecache \
&& yum -y install gcc \
&& yum -y install yum install -y pcre-devel \
&& yum -y install zlib zlib-devel \
&& yum -y install openssl openssl--devel \
&& cd /usr/nginx1.9.9/nginx-1.9.9/ && ./configure && make && make install #如果设置daemon off; nginx无法启动
#RUN echo "\ndaemon off;" >> /etc/nginx/nginx.conf # Commands when creating a new container
# 启动nginx 需进入/usr/local/nginx/sbin 执行./configure
CMD /bin/bash

最后执行命令"docker build -t nginx-centos:6.7 ."

其中.表示在当前目录下搜索Dockerfile文件,-t参数指定镜像名称和tag。

欢迎关注公众号「gushidefengzheng」古时的风筝

如何用Dockerfile创建镜像的更多相关文章

  1. docker——Dockerfile创建镜像

    写在前面: 继续docker的学习,昨天用docker成功跑了tomcat,但是在centos中镜像跑的容器手动装jdk和tomcat,今天学习用Dockerfile创建镜像,并在上面搭建java环境 ...

  2. Dockerfile创建镜像

    Dockerfile是一个文本格式的配置文件,用户可以使用Dockerfile来快速创建自定义的镜像. Dockerfile由一行行命令语句组成,并且支持易#开头的注释行. 一般而言Dockerfil ...

  3. docker常用命令、镜像命令、容器命令、数据卷,使用dockerFile创建镜像,dockefile的语法规则。

    一.docker常用命令? 1. 常用帮助命令 1.1 docker的信息以及版本号 /* docker info 查看docker的信息 images2 docker本身就是一个镜像. docker ...

  4. docker学习笔记6:利用dockerfile创建镜像介绍(生成简单web服务器镜像)

    本文介绍如何利用dockerfile来创建镜像.下面介绍具体的操作过程: 一.创建构建环境 操作示例如下: xxx@ubuntu:~$ pwd /home/xxx xxx@ubuntu:~$ mkdi ...

  5. 使用Dockerfile创建镜像

    Dockerfile是一个文本格式的配置文件,用户可以使用Dockerfile来快速创建自定义的镜像. 一.基本结构 Dockerfile由一行行命令语句组成,并且支持以#开头的注释行. 一般而言,D ...

  6. [转]Docker基础-使用Dockerfile创建镜像

    本文转自:https://www.cnblogs.com/jie-fang/p/7927643.html 1.基本结构 Dockerfile由一行行命令语句组成,并支持以#开头的注释行.例如: # T ...

  7. Docker基础-使用Dockerfile创建镜像

    1.基本结构 Dockerfile由一行行命令语句组成,并支持以#开头的注释行.例如: # This dockerfile uses the ubuntu image # VERSION 2 - ED ...

  8. Docker学习笔记之通过 Dockerfile 创建镜像

    0x00 概述 由于 Docker 镜像的结构优势,使它的占用空间远小于普通的虚拟机镜像,而这就大幅减少了 Docker 镜像在网络或者其他介质中转移所花费的时间,进而提高了我们进行迁移部署的效率.不 ...

  9. docker Dockerfile 创建镜像

    Docker 组件 1. docker client : docker的客户端 2. docker server : docker daemon的主要组成部分,接受用户通过docker client发 ...

随机推荐

  1. 伪共享(false sharing),并发编程无声的性能杀手

    在并发编程过程中,我们大部分的焦点都放在如何控制共享变量的访问控制上(代码层面),但是很少人会关注系统硬件及 JVM 底层相关的影响因素.前段时间学习了一个牛X的高性能异步处理框架 Disruptor ...

  2. 谈谈一些有趣的CSS题目(五)-- 单行居中,两行居左,超过两行省略

    开本系列,讨论一些有趣的 CSS 题目,抛开实用性而言,一些题目为了拓宽一下解决问题的思路,此外,涉及一些容易忽视的 CSS 细节. 解题不考虑兼容性,题目天马行空,想到什么说什么,如果解题中有你感觉 ...

  3. 计算机程序的思维逻辑 (60) - 随机读写文件及其应用 - 实现一个简单的KV数据库

    57节介绍了字节流, 58节介绍了字符流,它们都是以流的方式读写文件,流的方式有几个限制: 要么读,要么写,不能同时读和写 不能随机读写,只能从头读到尾,且不能重复读,虽然通过缓冲可以实现部分重读,但 ...

  4. Xamarin+Prism开发详解二:Xaml文件如何简单绑定Resources资源文件内容

    我们知道在UWP里面有Resources文件xxx.resx,在Android里面有String.Xml文件等.那跨平台如何统一这些类别不一的资源文件以及Xaml设计文件如何绑定这些资源?应用支持多国 ...

  5. [C#] C# 知识回顾 - 表达式树 Expression Trees

    C# 知识回顾 - 表达式树 Expression Trees 目录 简介 Lambda 表达式创建表达式树 API 创建表达式树 解析表达式树 表达式树的永久性 编译表达式树 执行表达式树 修改表达 ...

  6. MVC还是MVVM?或许VMVC更适合WinForm客户端

    最近开始重构一个稍嫌古老的C/S项目,原先采用的技术栈是『WinForm』+『WCF』+『EF』.相对于现在铺天盖地的B/S架构来说,看上去似乎和Win95一样古老,很多新入行的,可能就没有见过经典的 ...

  7. BPM助力企业数字化转型

    自九十年代末,流程管理开始引入国内,至今已经有20多年的历史了,由最初的部门级应用向企业级应用转变,大家的认知也经历了一系列的发展变化.不同阶段的信息化水平对企业的流程以及BPM平台也提出了不同的需求 ...

  8. iOS之开发中常用的颜色及其对应的RGB值

      R G B 值   R G B 值   R G B 值 黑色 0 0 0 #000000 黄色 255 255 0 #FFFF00 浅灰蓝色 176 224 230 #B0E0E6 象牙黑 41 ...

  9. git添加GitHub远程库

    已经在本地创建了一个Git仓库后,又想在GitHub创建一个Git仓库,并且让这两个仓库进行远程同步,这样,GitHub上的仓库既可以作为备份,又可以让其他人通过该仓库来协作 首先,登陆GitHub, ...

  10. Hadoop的安装与设置(1)

    在Ubuntu下安装与设置Hadoop的主要过程. 1. 创建Hadoop用户 创建一个用户,用户名为hadoop,在home下创建该用户的主目录,就不详细介绍了. 2. 安装Java环境 下载Lin ...