为什么要使用 Docker?
- 更高效的利用系统资源:不需要进行硬件虚拟以及运行完整操作系统等额外开;
- 更快速的启动时间:直接运行于宿主内核,无需启动完整的操作系统;
- 一致的运行环境:镜像提供了除内核外完整的运行时环境,确保了应用运行环境一致性;
- 持续交付和部署:通过定制应用镜像来实现持续集成、持续交付、部署;
- 更轻松的迁移:执行环境的一致性,使得应用的迁移更加容易; 6.更轻松的维护和扩展:分层存储以及镜像的技术,使得应用重复部分的复用更为容易,也使得应用的维护更新更加简单,基于基础镜像进一步扩展镜像也变得非常简单。此外,Docker团队同各个开源项目团队一起维护了一大批高质量的官方镜像;
Docker容器
- 镜像(Image)和容器(Container)的关系,就像是面向对象程序设计中的类和实例一样,镜像是静态的定义,容器是镜像运行时的实体。
- 容器的实质是进程,但与直接在宿主执行的进程不同,容器进程运行于属于自己的独立的命名空间。因此容器可以拥有 自己的root文件系统、自己的网络配置、自己的进程空间,甚至自己的用户ID空间。容器内的进程是运行在一个隔离的环境里,使用起来,就好像是在一个独立于宿主的系统下操作一样。这种特性使得容器封装的应用比直接在宿主运行更加安全。
- 容器存储层的生存周期和容器一样,容器消亡时,容器存储层也随之消亡。因此,任何保存于容器存储层的信息都会随 容器删除而丢失。
- 所有的文件写入操作,都应该使用数据卷(Volume)、或者绑定宿主目录,在这些位置的读写会跳过容器存储层,直接 对宿主(或网络存储)发生读写,其性能和稳定性更高。
Docker常用命令
- 列出镜像:docker image
Docker Hub 中显示的体积是压缩后的体积。在镜像下载和上传过程中镜像是保持着压缩状态的,因此 Docker Hub 所显示的大小是网络传输中更关心的流量大小。而docker images显示的是镜像下载到本地后,展开的大小,准确说,是展开后的各层所占空间的总和,因为镜像到本地后,查看空间的时候,更关心的是本地磁盘空间占用的大小。docker images 列表中的镜像体积总和并非是所有镜像实际硬盘消耗。由于 Docker镜像是多层存储结构,并且可以继承、复用,因此不同镜像可能会因为使用相同的基础镜像,从而拥有共同的层。由于 Docker 使用 Union FS,相同的层只需要保存一份即可,因此实际镜像硬盘占用空间很可能要比这个列表镜像大小的总和要小的多。 - 虚悬镜像
除了 docker pull 可能导致这种情况, docker build 也同样可以导致这种现象。由于新旧镜像同名,旧镜像名称被取消,从而出现仓库名、标签均为 <none>的镜像
Dockerfile命令
-
COPY 复制文件
- 格式:
COPY <源路径>... <目标路径>
COPY ["<源路径1>",... "<目标路径>"]
<源路径> 可以是多个,甚至可以是通配符,其通配符规则要满足 Go 的 filepath.Match 规 则,如:
COPY hom* /mydir/
COPY hom?.txt /mydir/
<目标路径> 可以是容器内的绝对路径,也可以是相对于工作目录的相对路径(工作目录可以 用 WORKDIR 指令来指定)。目标路径不需要事先创建,如果目录不存在会在复制文件前先行 创建缺失目录。 - 格式:
-
ADD 更高级的复制文件
-
CMD 容器启动命令
CMD 指令的格式和 RUN 相似,也是两种格式:
shell 格式: CMD <命令>
exec 格式: CMD ["可执行文件", "参数1", "参数2"...] 推荐使用exec命令,注意容器中进程不区分前后台进程概念。 -
ENTRYPOINT 入口点
Dockerfile注意事项
- 很多人初学Docker制作出了很臃肿的镜像的原因之一,就是忘记了每一层构建的最后一定要清理掉无关文件。