Docker容器技术介绍(七)--- Dockerfile简介

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/zhang197093/article/details/78655687

Docker 创建镜像有多种方式,比如之前介绍过的docker commit 命令可以把我们在容器中的修改保存并生成一个新的镜像,除此之外,我们还可以编写一个Dockerfile,然后根据这个Dockerfile去构建镜像,而Dockerfile包含了生成这个镜像的基本信息。

一个Dockerfile一般由四部分组成:基础镜像信息、维护者信息、镜像操作指令和容器启动时执行指令

首先我们来看一个简单的Dockerfile样例:

FROM scratch
ADD ubuntu-trusty-core-cloudimg-amd64-root.tar.gz /

# a few minor docker-specific tweaks
# see https://github.com/docker/docker/blob/9a9fc01af8fb5d98b8eec0740716226fadb3735c/contrib/mkimage/debootstrap
RUN set -xe \
	\
# https://github.com/docker/docker/blob/9a9fc01af8fb5d98b8eec0740716226fadb3735c/contrib/mkimage/debootstrap#L40-L48
	&& echo '#!/bin/sh' > /usr/sbin/policy-rc.d \
	&& echo 'exit 101' >> /usr/sbin/policy-rc.d \
	&& chmod +x /usr/sbin/policy-rc.d \
	\
# https://github.com/docker/docker/blob/9a9fc01af8fb5d98b8eec0740716226fadb3735c/contrib/mkimage/debootstrap#L54-L56
	&& dpkg-divert --local --rename --add /sbin/initctl \
	&& cp -a /usr/sbin/policy-rc.d /sbin/initctl \
	&& sed -i 's/^exit.*/exit 0/' /sbin/initctl \
	\
# https://github.com/docker/docker/blob/9a9fc01af8fb5d98b8eec0740716226fadb3735c/contrib/mkimage/debootstrap#L71-L78
	&& echo 'force-unsafe-io' > /etc/dpkg/dpkg.cfg.d/docker-apt-speedup \
	\
# https://github.com/docker/docker/blob/9a9fc01af8fb5d98b8eec0740716226fadb3735c/contrib/mkimage/debootstrap#L85-L105
	&& echo 'DPkg::Post-Invoke { "rm -f /var/cache/apt/archives/*.deb /var/cache/apt/archives/partial/*.deb /var/cache/apt/*.bin || true"; };' > /etc/apt/apt.conf.d/docker-clean \
	&& echo 'APT::Update::Post-Invoke { "rm -f /var/cache/apt/archives/*.deb /var/cache/apt/archives/partial/*.deb /var/cache/apt/*.bin || true"; };' >> /etc/apt/apt.conf.d/docker-clean \
	&& echo 'Dir::Cache::pkgcache ""; Dir::Cache::srcpkgcache "";' >> /etc/apt/apt.conf.d/docker-clean \
	\
# https://github.com/docker/docker/blob/9a9fc01af8fb5d98b8eec0740716226fadb3735c/contrib/mkimage/debootstrap#L109-L115
	&& echo 'Acquire::Languages "none";' > /etc/apt/apt.conf.d/docker-no-languages \
	\
# https://github.com/docker/docker/blob/9a9fc01af8fb5d98b8eec0740716226fadb3735c/contrib/mkimage/debootstrap#L118-L130
	&& echo 'Acquire::GzipIndexes "true"; Acquire::CompressionTypes::Order:: "gz";' > /etc/apt/apt.conf.d/docker-gzip-indexes \
	\
# https://github.com/docker/docker/blob/9a9fc01af8fb5d98b8eec0740716226fadb3735c/contrib/mkimage/debootstrap#L134-L151
	&& echo 'Apt::AutoRemove::SuggestsImportant "false";' > /etc/apt/apt.conf.d/docker-autoremove-suggests

# delete all the apt list files since they're big and get stale quickly
RUN rm -rf /var/lib/apt/lists/*
# this forces "apt-get update" in dependent images, which is also good

# enable the universe
RUN sed -i 's/^#\s*\(deb.*universe\)$/\1/g' /etc/apt/sources.list

# make systemd-detect-virt return "docker"
# See: https://github.com/systemd/systemd/blob/aa0c34279ee40bce2f9681b496922dedbadfca19/src/basic/virt.c#L434
RUN mkdir -p /run/systemd && echo 'docker' > /run/systemd/container

# overwrite this with 'CMD []' in a dependent Dockerfile
CMD ["/bin/bash"]


Dockerfile 的注释以 ‘#’ 开头


Dockerfile 的第一句非注释指令是基础镜像信息,用 FROM 关键字指定,比如这里的 FROMscratch 表示该镜像是在 scratch镜像基础上制作的


ADD 关键字可以把宿主机的文件添加到镜像中的指定位置, ADD ubuntu-trusty-core-cloudimg-amd64-root.tar.gz /

表示把宿主机中ubuntu-trusty-core-cloudimg-amd64-root.tar.gz 复制到容器中的 / 目录下


RUN 关键字可以用来运行shell命令,每一个RUN关键字会提交一次(相当于docker commit一次),产生一个层(Layer),所以如果不想有太多的层,应该一个RUN

关键字执行多个命令,比如 

RUN mkdir -p /run/systemd && echo 'docker' > /run/systemd/container
这条RUN命令 执行了 mkdir 和 echo 两个shell命令


CMD 指令指定容器运行时默认执行的命令,当你在启动容器时没有明确指定执行的COMMAND时就会用该CMD



常用指令介绍


1.FROM
指定所创建镜像的基础镜像,如果本地不存在,则默认会去Docker Hub下载指定镜像。
格式为FROM <image>,或FROM <image>:<tag>,或FROM <image>@<digest>。


2.RUN
运行指定命令。
格式为RUN <command>或 RUN ["executable","param1","param2"]。注意,后一个指令会被解析为Json数组,因此必须用

双引号。前者默认将在shell终端中运行命令,即/bin/sh -c;后者则使用exec执行,不会启动shell环境。
指定使用其他终端类型可以通过第二种方式实现,例如RUN ["/bin/bash","-c","echo hello"]。
每条RUN指令将在当前镜像的基础上执行指定命令,并提交为新的镜像。当命令较长时可以使用\来换行。


3.CMD
CMD指令用来指定启动容器时默认执行的命令。它支持三种格式:

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


4.LABEL
LABEL指令用来指定生成镜像的元数据标签信息。
格式为LABEL<key>=<value><key>=<value><key>=<value>...。
例如:

LABEL maintainer="[email protected]"
来指定作者


5.EXPOSE
声明镜像内服务所监听的端口。
格式为EXPOSE <port> [<port>...]。
例如:
EXPOSE 22 80
注意,该指令只是起到声明作用,并不会自动完成端口映射。


6.ENV
指定环境变量,在镜像生成过程中会被后续RUN指令使用,在镜像启动的容器中也会存在。
格式为ENV <key> <value> 或 ENV <key>=<value>...。
例如:

ENV VERSION 14.04


7.ADD
该命令将复制指定的<src>路径下的内容到容器中的<dest>路径下。
格式为ADD <src> <dest>。
其中<src>可以是Dockerfile所在目录的一个相对路径(文件或目录),也可以是一个URL,还可以是

一个tar文件(如果为tar文件,会自动解压到<dest>路径下)。

<dest>可以是镜像内的绝对路径,或者相对于工作目录(WORKDIR)的相对路径。


8.COPY
格式为COPY <src> <dest>。

COPY 命令和ADD 非常类似,只是COPY命令只支持把宿主机的文件拷贝到镜像中,一般这种情况下推荐使用COPY命令。

目标路径不存在时,会自动创建。


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


完整的指令请查阅:Dockerfile reference


接下来,我们使用 centos:6.9 作为基础镜像,搭建一个Nginx镜像

Dockerfile:

#设置基础镜像
FROM centos:6.9

#作者信息
LABEL [email protected]


#开放端口
EXPOSE 80

#安装Nginx
RUN yum makecache && yum install -y --nogpgcheck epel-release && yum install -y --nogpgcheck nginx

#关闭Nginx守护进程
RUN sed -in '3a daemon off;' /etc/nginx/nginx.conf

#启动Nginx
CMD ["/usr/sbin/nginx", "-c", "/etc/nginx/nginx.conf"]

然后使用docker build 命令来构建镜像

[root@localhost sshd_ubuntu]# docker build --help

Usage: docker build [OPTIONS] PATH | URL | -

Build a new image from the source code at PATH

  -c, --cpu-shares=0    CPU shares (relative weight)
  --cgroup-parent=      Optional parent cgroup for the container
  --cpu-period=0        Limit the CPU CFS (Completely Fair Scheduler) period
  --cpu-quota=0         Limit the CPU CFS (Completely Fair Scheduler) quota
  --cpuset-cpus=        CPUs in which to allow execution (0-3, 0,1)
  --cpuset-mems=        MEMs in which to allow execution (0-3, 0,1)
  -f, --file=           Name of the Dockerfile (Default is 'PATH/Dockerfile')
  --force-rm=false      Always remove intermediate containers
  --help=false          Print usage
  -m, --memory=         Memory limit
  --memory-swap=        Total memory (memory + swap), '-1' to disable swap
  --no-cache=false      Do not use cache when building the image
  --pull=false          Always attempt to pull a newer version of the image
  -q, --quiet=false     Suppress the verbose output generated by the containers
  --rm=true             Remove intermediate containers after a successful build
  -t, --tag=            Repository name (and optionally a tag) for the image

在Dockerfile所在的目录执行
docker build -t lamp:nginx .

[root@localhost sshd_ubuntu]# ls
Dockerfile
[root@localhost sshd_ubuntu]# docker build -t lnmp:nginx .
Sending build context to Docker daemon 2.048 kB
Sending build context to Docker daemon 
Step 0 : FROM centos:6.9
 ---> e071bce628ba
Step 1 : LABEL maintainer [email protected]
 ---> Using cache
 ---> 0d618389ca76
Step 2 : EXPOSE 80
 ---> Using cache
 ---> fc6a935299ab
Step 3 : RUN yum makecache && yum install -y --nogpgcheck epel-release && yum install -y --nogpgcheck nginx
 ---> Running in 62cacd14c2ed
Loaded plugins: fastestmirror, ovl
............
Complete!
 ---> ad23365869fb
Removing intermediate container 62cacd14c2ed
Step 4 : RUN sed -in '3a daemon off;' /etc/nginx/nginx.conf
 ---> Running in b763f003f645
 ---> 302402a29363
Removing intermediate container b763f003f645
Step 5 : CMD /usr/sbin/nginx -c /etc/nginx/nginx.conf
 ---> Running in b0c755098664
 ---> 7befb6b4f77a
Removing intermediate container b0c755098664
Successfully built 7befb6b4f77a

看到 Successfully build xxx 表示构建成功,使用docker images 查看

[root@localhost sshd_ubuntu]# docker images
REPOSITORY            TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
lnmp                  nginx               7befb6b4f77a        46 seconds ago      948.1 MB
nginx                 myself              ffbf82fc975d        3 hours ago         108.3 MB
ubuntu                sshd2               f5e51900b258        8 hours ago         382.9 MB
centos                6.9                 e071bce628ba        3 weeks ago         194.7 MB
php                   5.6.32-fpm          57a62c38abf7        4 weeks ago         369.2 MB
nginx                 latest              2ecc072be0ec        7 weeks ago         108.3 MB
ubuntu                14.04               b44ce450cb60        10 weeks ago        188 MB
quay.io/coreos/etcd   v3.0.4              3b17a5f34e6c        16 months ago       43.3 MB

测试运行该镜像

[root@localhost sshd_ubuntu]# docker run -d -p 8080:80 lnmp:nginx
f49435d6ccb956cad18535a3b40fa8c89d1fbd14e6d3e326e175221823d23858
[root@localhost sshd_ubuntu]# docker ps --no-trunc
CONTAINER ID                                                       IMAGE               COMMAND                                      CREATED             STATUS              PORTS                  NAMES
f49435d6ccb956cad18535a3b40fa8c89d1fbd14e6d3e326e175221823d23858   lnmp:nginx          "/usr/sbin/nginx -c /etc/nginx/nginx.conf"   14 seconds ago      Up 14 seconds       0.0.0.0:8080->80/tcp   happy_einstein      
[root@localhost sshd_ubuntu]# curl '127.0.0.1:8080'
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
    <head>
        <title>Test Page for the Nginx HTTP Server on EPEL</title>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
        <style type="text/css">
            /*<![CDATA[*/
            body {
                background-color: #fff;

这样一个基于centos的nginx镜像就构建好了,你可以把该镜像push到Docker Hub上供别人下载使用 :)

That's it!











猜你喜欢

转载自blog.csdn.net/zhang197093/article/details/78655687