Alipne镜像Dockerfile构建自己的镜像

Posted qlqwjy

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Alipne镜像Dockerfile构建自己的镜像相关的知识,希望对你有一定的参考价值。

1.Alipne镜像

  目前比较流行的 rootfs 应该就是 alpine 了,因为他的体积特别小,最简单的环境只需要 5M 。Docker 官方已开始推荐使用 Alpine 替代之前的 Ubuntu 做为基础镜像环境。

  Alpine 操作系统是一个面向安全的轻型 Linux 发行版。它不同于通常 Linux 发行版,Alpine 采用了 musl libc 和 busybox 以减小系统的体积和运行时资源消耗,但功能上比 busybox 又完善的多,因此得到开源社区越来越多的青睐。在保持瘦身的同时,Alpine 还提供了自己的包管理工具 apk,可以通过 https://pkgs.alpinelinux.org/packages 网站上查询包信息,也可以直接通过 apk 命令直接查询和安装各种软件。

  Alpine 由非商业组织维护的,支持广泛场景的 Linux发行版,它特别为资深/重度Linux用户而优化,关注安全,性能和资源效能。Alpine 镜像可以适用于更多常用场景,并且是一个优秀的可以适用于生产的基础系统/环境。

  Alpine Docker 镜像也继承了 Alpine Linux 发行版的这些优势。相比于其他 Docker 镜像,它的容量非常小,仅仅只有 5 MB 左右(对比 Ubuntu 系列镜像接近 200 MB),且拥有非常友好的包管理机制。官方镜像来自 docker-alpine 项目。

  目前 Docker 官方已开始推荐使用 Alpine 替代之前的 Ubuntu 做为基础镜像环境。这样会带来多个好处。包括镜像下载速度加快,镜像安全性提高,主机之间的切换更方便,占用更少磁盘空间等。

下表是官方镜像的大小比较:

技术图片

 

   一句话,alpine可以替代Ubuntu作为基础镜像。体积小。

 

直接运行alpine进行下载:

E:dockerdockerTestdockerfiletest>docker run alpine echo 123
Unable to find image alpine:latest locally
latest: Pulling from library/alpine
c9b1b535fdd9: Pull complete
Digest: sha256:ab00606a42621fb68f2ed6ad3c88be54397f981a7b70a79db3d1172b11c4367d
Status: Downloaded newer image for alpine:latest
123

E:dockerdockerTestdockerfiletest>docker images
REPOSITORY                    TAG                 IMAGE ID            CREATED             SIZE
alpine                        latest              e7d92cdc71fe        3 weeks ago         5.59MB
hello-world                   latest              fce289e99eb9        13 months ago       1.84kB
hub.c.163.com/library/nginx   latest              46102226f2fd        2 years ago         109MB
hub.c.163.com/library/nginx   1.9                 af4b3d7d5401        3 years ago         191MB

2.制作简单的镜像

1.什么是dockerfile?

  Dockerfile 是一个用来构建镜像的文本文件,文本内容包含了一条条构建镜像所需的指令和说明。相当于告诉docker我要做什么事情。

2.docker build

  相当于是执行dockerfile里面的每一件事情,制作一个镜像。

3.构建第一个镜像

(1)新建一个干净的文件夹下面建一个Dockerfile文件,内容如下:

FROM alpine:latest
MAINTAINER qlq qlq@163.com
CMD echo "hello dockerfile"

如下:

E:dockerdockerTestdockerfiletest>ls
Dockerfile

E:dockerdockerTestdockerfiletest>cat Dockerfile
FROM alpine:latest
MAINTAINER qlq qlq@163.com
CMD echo "hello dockerfile"

解释:

FROM:定制的镜像都是基于 FROM 的镜像,这里的 alpine就是定制需要的基础镜像。后续的操作都是基于 alpine。

MAINTAINER: 指定镜像的作者名称和邮箱(可以省略)

CMD:需要执行的命令,相当于在shell脚本中执行的命令。

 

补充:与CMD有相同功能的有RUN、ENTRYPOINT,三个都能执行命令,但是有区别:

RUN命令执行命令并创建新的镜像层,通常用于安装软件包。在构建镜像的时候执行。

CMD命令设置容器启动后默认执行的命令及其参数,但CMD设置的命令能够被docker run命令后面的命令行参数替换。此命令会在容器启动且 docker run 没有指定其他命令时运行。

ENTRYPOINT配置容器启动时的执行命令(不会被忽略,一定会被执行,即使运行 docker run时指定了其他命令)。相当于是容器的入口。

 

我们可用两种方式指定 RUN、CMD 和 ENTRYPOINT 要运行的命令:Shell 格式和 Exec 格式:

Shell格式:<instruction> <command>。例如:apt-get install python3

Exec格式:<instruction> ["executable", "param1", "param2", ...]。例如: ["apt-get", "install", "python3"]

  CMD 和 ENTRYPOINT 推荐使用 Exec 格式,因为指令可读性更强,更容易理解。RUN 则两种格式都可以。  

 

注意:Dockerfile 的RUN指令每执行一次都会在 docker 上新建一层。所以过多无意义的层,会造成镜像膨胀过大。例如:

FROM centos
RUN yum install wget
RUN wget -O redis.tar.gz "http://download.redis.io/releases/redis-5.0.3.tar.gz"
RUN tar -xvf redis.tar.gz
以上执行会创建 3 层镜像。可简化为以下格式:
FROM centos
RUN yum install wget     && wget -O redis.tar.gz "http://download.redis.io/releases/redis-5.0.3.tar.gz"     && tar -xvf redis.tar.gz

 

(2)构建镜像:

E:dockerdockerTestdockerfiletest>docker build -t hello_dockerfile . #构建镜像
Sending build context to Docker daemon  2.048kB
Step 1/3 : FROM alpine:latest
 ---> e7d92cdc71fe
Step 2/3 : MAINTAINER qlq qlq@163.com
 ---> Running in 0eed5430920c
Removing intermediate container 0eed5430920c
 ---> 099d9254c7b7
Step 3/3 : CMD echo "hello dockerfile"
 ---> Running in 70ba59845b28
Removing intermediate container 70ba59845b28
 ---> 779eab29d6dc
Successfully built 779eab29d6dc
Successfully tagged hello_dockerfile:latest
SECURITY WARNING: You are building a Docker image from Windows against a non-Windows Docker host. All files and directories added to build context will have -rwxr-xr-x permissions. It is recommended to double check and reset permissions for sensitive files and directories.

E:dockerdockerTestdockerfiletest>docker images #运行镜像
REPOSITORY                    TAG                 IMAGE ID            CREATED             SIZE
hello_dockerfile              latest              779eab29d6dc        5 seconds ago       5.59MB
alpine                        latest              e7d92cdc71fe        3 weeks ago         5.59MB
hello-world                   latest              fce289e99eb9        13 months ago       1.84kB
hub.c.163.com/library/nginx   latest              46102226f2fd        2 years ago         109MB
hub.c.163.com/library/nginx   1.9                 af4b3d7d5401        3 years ago         191MB


E:dockerdockerTestdockerfiletest>docker run hello_dockerfile
hello dockerfile

解释:

docker build -t hello_dockerfile .

 

(1)构建镜像时的-t表示给镜像一个tag,可以指定为name:version形式。

(2) 最后的点代表上下文路径,是指 docker 在构建镜像,有时候想要使用到本机的文件(比如复制),docker build 命令得知这个路径后,会将路径下的所有内容打包。

  由于 docker 的运行模式是 C/S。我们本机是 C,docker 引擎是 S。实际的构建过程是在 docker 引擎下完成的,所以这个时候无法用到我们本机的文件。这就需要把我们本机的指定目录下的文件一起打包提供给 docker 引擎使用。

  如果未说明最后一个参数,那么默认上下文路径就是 Dockerfile 所在的位置。

注意:上下文路径下不要放无用的文件,因为会一起打包发送给 docker 引擎,如果文件过多会造成过程缓慢。

4.指令详解-Dockerfile语法

0.FROM

  基础镜像。定制的镜像都是基于 FROM 的镜像。下面的操作都是基础该镜像。

1.RUN

  用于执行后面跟着的命令行命令。只在构建镜像的时候执行,一般用于构建镜像的时候下载文件。

语法:

shell格式:

RUN <命令行命令>
# <命令行命令> 等同于,在终端操作的 shell 命令。

exec格式:

RUN ["可执行文件", "参数1", "参数2"]
# 例如:
# RUN ["./test.php", "dev", "offline"] 等价于 RUN ./test.php dev offline

2. COPY

  复制指令,从上下文目录中复制文件或者目录到容器里指定路径。

语法:

COPY [--chown=<user>:<group>] <源路径1>...  <目标路径>
COPY [--chown=<user>:<group>] ["<源路径1>",...  "<目标路径>"]

[--chown=<user>:<group>]:可选参数,用户改变复制到容器内文件的拥有者和属组。

<源路径>:源文件或者源目录,这里可以是通配符表达式,其通配符规则要满足 Go 的 filepath.Match 规则。

<目标路径>:容器内的指定路径,该路径不用事先建好,路径不存在的话,会自动创建。

3. ADD

  ADD 指令和 COPY 的使用格式一致(同样需求下,官方推荐使用 COPY)。Add还可以将远程的文件拷贝到目录下,比如http服务器上文件。与COPY不同之处如下:

ADD 的优点:在执行 <源文件> 为 tar 压缩文件的话,压缩格式为 gzip, bzip2 以及 xz 的情况下,会自动复制并解压到 <目标路径>。

ADD 的缺点:在不解压的前提下,无法复制 tar 压缩文件。会令镜像构建缓存失效,从而可能会令镜像构建变得比较缓慢。具体是否使用,可以根据是否需要自动解压来决定。

4.CMD

  类似于 RUN 指令,用于运行程序,但二者运行的时间点不同:

CMD 在docker run 时运行。

RUN 是在 docker build。

  作用:为启动的容器指定默认要运行的程序,程序运行结束,容器也就结束。CMD 指令指定的程序可被 docker run 命令行参数中指定要运行的程序所覆盖。

  注意:如果 Dockerfile 中如果存在多个 CMD 指令,仅最后一个生效。

5.ENTRYPOINT(一般用作容器的入口)

类似于 CMD 指令,但其不会被 docker run 的命令行参数指定的指令所覆盖,而且这些命令行参数会被当作参数送给 ENTRYPOINT 指令指定的程序。

但是, 如果运行 docker run 时使用了 --entrypoint 选项,此选项的参数可当作要运行的程序覆盖 ENTRYPOINT 指令指定的程序。

优点:在执行 docker run 的时候可以指定 ENTRYPOINT 运行所需的参数。

注意:如果 Dockerfile 中如果存在多个 ENTRYPOINT 指令,仅最后一个生效。

6.ENV

  设置环境变量,定义了环境变量,那么在后续的指令中,就可以使用这个环境变量。

语法:

ENV <key> <value>
ENV <key1>=<value1> <key2>=<value2>...

7.ARG

构建参数,与 ENV 作用一至。不过作用域不一样。ARG 设置的环境变量仅对 Dockerfile 内有效,也就是说只有 docker build 的过程中有效,构建好的镜像内不存在此环境变量。

构建命令 docker build 中可以用 --build-arg <参数名>=<值> 来覆盖。

语法:

ARG <参数名>[=<默认值>]

8.VOLUME(重要)

定义匿名数据卷。在启动容器时忘记挂载数据卷,会自动挂载到匿名卷。

语法:

VOLUME ["<路径1>", "<路径2>"...]
VOLUME <路径>

作用:

避免重要的数据,因容器重启而丢失,这是非常致命的。

避免容器不断变大。

可以做到多个容器共享数据。

9.EXPOSE

仅仅只是声明端口。

语法:

EXPOSE <端口1> [<端口2>...]

作用:

帮助镜像使用者理解这个镜像服务的守护端口,以方便配置映射。

在运行时使用随机端口映射时,也就是 docker run -P 时,会自动随机映射 EXPOSE 的端口。

10.WORKDIR

指定工作目录。用 WORKDIR 指定的工作目录,会在构建镜像的每一层中都存在。(WORKDIR 指定的工作目录,必须是提前创建好的)。

docker build 构建镜像过程中的,每一个 RUN 命令都是新建的一层。只有通过 WORKDIR 创建的目录才会一直存在。

语法:

WORKDIR <工作目录路径>

3. 基于nginx构建镜像

1.创建Dockerfile文件,内容如下

FROM ubuntu
MAINTAINER qlq qlq@163.com
RUN apt-get update
RUN apt-get install -y nginx
COPY index.html /var/www/html
ENTRYPOINT ["/usr/sbin/nginx", "-g", "daemon off;"]
EXPOSE 80

解释:

(1)FROM...指定镜像依赖于ubuntu镜像

(2)MAINTAINER...指定镜像维护者信息

(3)RUN apt-get update 相当于在ubuntu系统中执行更新软件

(4)RUN apt-get install -y nginx 是ubuntu系统安装nginx,-y表示直接安装不询问。

(5)COPY inde... 是将当前目录下的index.html拷贝到镜像中/var/www/html 目录下。(nginx默认的首页在此目录下,相当于更换nginx默认首页)

(6)ENTRYPOINT... 是执行命令,相当于运行镜像时执行"/usr/sbin/nginx -g daemon off;"

(7)EXPOSE 80 是指定该容器的端口是80

 

index.html内容如下:

"今天是周五!!!"

2.构建镜像

docker build -t qlq/hello-nginx .

3.查看镜像并且运行镜像

E:dockerdockerTestdockerfiletest2>docker images
REPOSITORY                    TAG                 IMAGE ID            CREATED             SIZE
qlq/hello-nginx               latest              8d51cb07e20b        3 minutes ago       152MB
hello_dockerfile              latest              779eab29d6dc        About an hour ago   5.59MB
alpine                        latest              e7d92cdc71fe        3 weeks ago         5.59MB
ubuntu                        latest              ccc6e87d482b        4 weeks ago         64.2MB
hello-world                   latest              fce289e99eb9        13 months ago       1.84kB
hub.c.163.com/library/nginx   latest              46102226f2fd        2 years ago         109MB
hub.c.163.com/library/nginx   1.9                 af4b3d7d5401        3 years ago         191MB

E:dockerdockerTestdockerfiletest2>docker run -d -p 8070:80 qlq/hello-nginx #运行镜像,将本机8070端口映射到容器的80端口
0055dcf8b0bb792e06627eb10b0f817e039f15c4a00411346d99ebcab6521220

E:dockerdockerTestdockerfiletest2>docker ps -a
CONTAINER ID        IMAGE               COMMAND                   CREATED             STATUS                         PORTS                  NAMES
0055dcf8b0bb        qlq/hello-nginx     "/usr/sbin/nginx -g …"    45 seconds ago      Up 43 seconds                  0.0.0.0:8070->80/tcp   wizardly_buck
b9b2d73a9b27        hello_dockerfile    "/bin/sh -c ‘echo "h…"   About an hour ago   Exited (0) About an hour ago                          frosty_sammet
0a75d125d0c5        alpine              "echo ‘123‘"              About an hour ago   Exited (0) About an hour ago                          silly_murdock

4.本地浏览器访问nginx服务

  由于我这里是windows虚拟机访问,因为docker是运行在Linux上的,在Windows中运行docker,实际上还是在Windows下先安装了一个Linux环境,然后在这个系统中运行的docker。也就是说,所有的东西都是在虚拟的linux环境中,而不是我们的宿主环境Windows。所以我们也不能通过localhost直接访问。需要先查看linux虚拟环境的IP,如下:查看本机虚拟linux环境的ip地址

E:dockerdockerTestdockerfiletest2>docker-machine ip default
192.168.99.100

 

浏览器访问:

技术图片

 

 

以上是关于Alipne镜像Dockerfile构建自己的镜像的主要内容,如果未能解决你的问题,请参考以下文章

Dockerfile详解,以及构建自定义镜像

DockerFile练习之构建自己的镜像

Dockerfile语法自定义镜像构建详解

Docker:Dockerfile自定义镜像

编写Dockerfile文件,构建自己的centos镜像

Dockerfile 定制专属镜像