Docker commit & Dockerfile
众所周知,容器是在镜像的基础,即一个系统他没有服务、程序他根本不算是一个系统,因此执行 docker run 的时候都会指定哪一个镜像作为容器的基础进行运行,在学习完镜像后,我们也尝试了 Docker hub 上的 Public Repository 给我们带来的便捷,本章我们主要通过 Docker commit 来了解 Docker 的构成。
Build image
你可以通过 docker run --name webserver -d -p 8081:80 nginx 去构建一个 nginx 服务器,并命名为 webserver,将其映射到宿主机的 8081 端口上,之后你可以访问 欢迎来到nginx! 去查看。
当构建完成后我们可以通过 docker exec -it webserver bash 中在正常 Linux 服务器上使用同样的操作进入到 /usr/share/nginx/html/ 目录下去自定义我们的内容,之后退出即可,当在访问 欢迎来到nginx! 的时候其更改的内容也会变动。
1 | 这主要涉及到修改了容器的文件,即容器的存储层,你可以通过 ```docker diff``` 看到具体的改动 |
之后,我们可以通过 docker commit 命令来将容器的存储层保存下来成为镜像,主要是在容器的基础上加上了存储层,使得有了数据,之后你改动也是直接覆盖存储层上,以后我们更改并运行这个镜像的时候,就会拥有这个容器最后的文件变化。
1 | ❯ docker commit -a "sun.lk<lk.sun@jiangxue.team>" -m "Upgrate:home file of info" webserver nginx:mytest |
上述命令主要通过 docker commit 来提交者信息,其中 -a 参数主要用于描述提交者信息,而 -m 于 github 一样用于描述提交,之后的 webserver 是容器的名字以及 image:tag 等,这些你可以在 Docker Desktop 中以图形化或者 docker image ls nginx 的方式进行查看,更多的可以参考 docker 容器提交|Docker 文档
1 | ❯ docker image ls nginx |
1 | 当然我们也可以通过 [docker 历史|Docker 文档](https://docs.docker.com/engine/reference/commandline/history/) 文档中记载的 ```docker history``` 来查看历史提交,比如 ```❯ docker history -H nginx:mytest``` 来查看 image 的历史记录 |
Run image
当定制好 Image 之后,我们可以通过 docker run --name web -d -p 8082:80 nginx:mytest 来进行运行, 将 nginx:mytest 镜像命名为新的服务为 web,并映射到宿主机的 8082 端口,之后访问 localhost:8082 其内容于我们 build image 的数据完美无瑕。
在 Docker Desktop 中,你可以通过图形化的方式将镜像上传到 Docker Hub 中,这与 GitHub 非常类似,之后你也可以发布属于你自己的容器镜像,供他人使用。
1 | docker commit 只是非常直观的演示 image&container 的概念,但由于全程黑箱操作,这也意味着他人使用起来也不会立马就知道这个镜像是做什么的,对于之后的维护是非常痛苦的。 |
Dockerfile
在上述的 “ Run image” 章节中,了解到镜像的制作我无非就是添加文件、配置然后修改、安装、构建、操作的命令携程脚本,之后用脚本构建、定制镜像,以此来解决之前黑箱操作透明性和可读性不强的问题,通过 Dockerfile 就可以很好的解决。
制作 Dockerfile 之前,我们首先在指定磁盘中建立一个文件夹,并进入到此文件夹中,创建一个新的文本文件,命名为 Dockerfile 即可,比如我们要通过 Dockerfile 来实现在 Buid image 章节中的修改 nginx 下的 index.html 文件,我们可以写入:
1 | FROM nginx |
其中FROM指令主要是指定基础镜像,而之后的RUN则是运行命令,你甚至可以将他当作 shell 脚本去写,更多的你可以参考Best practices for writing Dockerfiles | Docker Documentation写的非常详细。
Build image
之后,在Dockerfile文件所在的目录内运行 ❯ docker build -t nginx:mytest-v1 . 需要注意的是,我们使用的 docker build 命令下的 -t 参数主要用于指定 Name:tag 然后通过 “.” 来表示当前目录下进行构建。
1 | 一般来说 Dockerfile 放置在空目录下或者项目的根目录,然后根据上下文对镜像进行构建,同样的你可以通过 ```-d``` 参数来搭配上下文指定某个文件作为 Dockerfile,在 Docker 中并没有前置性的要求,只不过大家习惯了直接以 Dockerfile 命名的方式。 |
Docker build 还可支持铜鼓 git repo 进行构建,这将克隆 GitHub 存储库,并将克隆的存储库用作上下文存储库根目录下的 Dockerfile 用作 Dockerfile。您可以使用 或 方案指定任意 Git 存储库,当然者并不拘束于你使用 HTTP 还是 Git 的传g输方式。
当然 Docker 还不仅仅局限于 HTTP 和 Git 的传输方式,它还支持压缩文件的形势来进行构建,你可以继续查阅 docker build |Docker 文档 获取更多的信息。构建完成后你可以通过 localhost:8083 来进行访问,结果和上面我们使用 Docker commit 方式构建的结果还是一摸一样的。
对于之后的 Dockerfile 指令,可以通过 编写 Dockerfiles |的最佳实践Docker 文档 进行查阅,剩下的指令 :
| Name | Info | Url |
|---|---|---|
| LABEL | 标签,一个 image 可以拥有多个标签,可以通过标签来组织镜像的记录、许可等信息,同时用于批注容器、卷和网络之间,可以理解为注释 | 编写 Dockerfiles 的最佳实践Docker 文档 |
| FROM | 编写 Dockerfile 的入口,即指定 image | |
| RUN | 构建 Docker image 时所触发的命令 | |
| CMD | 在启动创建 docker image 时所触发的命令 | Dockerfile中RUN和CMD之间的区别 (qastack.cn) |
| EXPOSE | 声明容器运行时所提供的服务端口(仅仅是一个什么声明,在容器运行的时候不会因为他就会开启这个服务端口,但之后使用 docker run -P 时,也许会使用 EXPOSE 的端口) |
|
| ENV | 设置环境变量,可配合 RUN 进行使用 |
ENV 设置环境变量 - Docker —— 从入门到实践 (gitbook.io) 比官方文档写的更加直观 |
| COPY | 复制 | |
| ADD | 复制,COPY 的升级版,可以通过 URI 等形势进行,同时,也可以通过 --chown=<user>:<group> 来改变文件的所属用户的组 |
|
| ENTRYPOINT | 我理解为是 RUN 在容器启动中时所执行的命令的实现 | Dockerfile 中的 ENTRYPOINT. ENTRYPOINT是 Dockerfile 定义的一个指令,他的作用类似于… by Justin Chien Medium 直观了解 ENTRYPOINT 的作用 |
| VOLUME | 为了让数据持久化以及共享容器之间的数据,通过 VOLUME 指令绕过默认的联合文件系统,以正常的文件\目录的形势存储在宿主机上 | volume详解 · Docker – 从入门到实战 (baoshu.red) or 深入理解Docker Volume(一) - DockOne.io 配合阅读深入理解 |
| USER | 指定用户 | |
| WORKDIR | 工作目录 | Dockerfile reference Docker 文档 |
