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:\docker\dockerTest\dockerfiletest>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:\docker\dockerTest\dockerfiletest>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:\docker\dockerTest\dockerfiletest>ls Dockerfile E:\docker\dockerTest\dockerfiletest>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:\docker\dockerTest\dockerfiletest>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:\docker\dockerTest\dockerfiletest>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:\docker\dockerTest\dockerfiletest>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:\docker\dockerTest\dockerfiletest2>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:\docker\dockerTest\dockerfiletest2>docker run -d -p 8070:80 qlq/hello-nginx #运行镜像,将本机8070端口映射到容器的80端口 0055dcf8b0bb792e06627eb10b0f817e039f15c4a00411346d99ebcab6521220 E:\docker\dockerTest\dockerfiletest2>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:\docker\dockerTest\dockerfiletest2>docker-machine ip default 192.168.99.100
浏览器访问: