Docker入门
Docker
Docker 是什么
- 基于Linux 内核的Cgroup,Namespace,以及Union FS等技术,对进程进行封装隔离,属于操作系统 层面的虚拟化技术,由于隔离的进程独立于宿主和其它的隔离的进程,因此也称其为容器。
- 最初实现是基于LXC,从0.7 以后开始去除LXC,转而使用自行开发的Libcontainer,从1.11 开始,则 进一步演进为使用runC和Containerd。
- Docker 在容器的基础上,进行了进一步的封装,从文件系统、网络互联到进程隔离等等,极大的简化了容 器的创建和维护,使得Docker 技术比虚拟机技术更为轻便、快捷。
虚拟机和容器运行态的对比
虚拟机 (VM):
- 完整虚拟化: 每个虚拟机运行一个完整的操作系统实例,包括内核和用户空间。
- 虚拟化层: 虚拟机依赖于一个虚拟化管理器(如 VMware、Hyper-V 或 KVM),通过 Hypervisor 模拟硬件。
- 独立性: 每个虚拟机完全隔离,拥有自己的虚拟硬件和操作系统。
容器:
- 操作系统级虚拟化: 容器共享主机操作系统的内核,每个容器运行自己的用户空间。
- 轻量级: 容器通过使用 Linux 的内核功能(如 cgroups 和 namespaces)实现资源隔离。
- 共享内核: 容器不需要完整的操作系统实例,只包含必要的库和应用程序。

容器操作
- 启动 docker run
- -it 交互
- -d 后台运行
- -p 端口映射
- -v 磁盘挂载
- 启动已终止的容器
- docker start
- 停止容器
- docker stop
- 查看容器进程
- docker ps
- 查看容器细节
docker inspect
Dockerfile
理解构建上下文(Build Context)
- 当运行dockerbuild命令时,当前工作目录被称为构建上下文。
- dockerbuild 默认查找当前目录的Dockerfile作为构建输入,也可以通过–f指定Dockerfile。
- docker build –f ./Dockerfile
- 当dockerbuild运行时,首先会把构建上下文传输给dockerdaemon,把没用的文件包含在构建上下文时,会 导致传输时间长,构建需要的资源多,构建出的镜像大等问题。
- 试着到一个包含文件很多的目录运行下面的命令,会感受到差异;
- docker build -f $GOPATH/src/github.com/cncamp/golang/httpserver/Dockerfile ;
- docker build $GOPATH/src/github.com/cncamp/golang/httpserver/;
- 可以通过.dockerignore文件从编译上下文排除某些文件。
- 因此需要确保构建上下文清晰,比如创建一个专门的目录放置Dockerfile,并在目录中运行dockerbuild。
Dockerfile 常见命令
- FROM:选择基础镜像,推荐alpine
FROM [--platform=] <image>[@<digest>] [AS name ]
- LABELS:按标签组织项目
LABEL multi.label1="value1" multi.label2="value2" other="value3”
配合labelfilter 可过滤镜像查询结果
docker images -f label=multi.label1="value1"
- RUN:执行命令
最常见的用法是RUN apt-get update && apt-get install,这两条命令应该永远用&&连接,如果分开执行,RUN apt-get update 构建层被缓存,可能会导致新package无法安装
- CMD:容器镜像中包含应用的运行命令,需要带参数
CMD ["executable", "param1", "param2"…]
- EXPOSE:发布端口
EXPOSE <port> [<port>/<protocol>...]
是镜像创建者和使用者的约定
在dockerrun –P时,docker会自动映射expose的端口到主机大端口,如0.0.0.0:32768->80/tcp
- ENV 设置环境变量
ENV <key>=<value> ...
- ADD:从源地址(文件,目录或者URL)复制文件到目标路径
ADD [--chown=<user>:<group>] <src>... <dest>
ADD [--chown=<user>:<group>] [“<src>”,... “<dest>”] (路径中有空格时使用
- ADD支持Go风格的通配符,如ADD check* /testdir/
- src如果是文件,则必须包含在编译上下文中,ADD 指令无法添加编译上下文之外的文件
- src如果是URL,如果dest结尾没有/,那么dest是目标文件名,如果dest结尾有/,那么dest是目标目录名
- 如果src是一个目录,则所有文件都会被复制至dest
- 如果src是一个本地压缩文件,则在ADD 的同时完整解压操作
- 如果dest不存在,则ADD 指令会创建目标目录
- 应尽量减少通过ADDURL 添加remote 文件,建议使用curl 或者wget&& untar
- COPY:从源地址(文件,目录或者URL)复制文件到目标路径
COPY [--chown=<user>:<group>] <src>... <dest>
COPY [--chown=<user>:<group>] ["<src>",... "<dest>"] // 路径中有空格时使用
- COPY的使用与ADD类似,但有如下区别
- COPY 只支持本地文件的复制,不支持URL
- COPY 不解压文件
- COPY可以用于多阶段编译场景,可以用前一个临时镜像中拷贝文件
- COPY --from=build /bin/project /bin/projec
COPY 语义上更直白,复制本地文件时,优先使用COPY
- ENTRYPOINT:定义可以执行的容器镜像入口命令
ENTRYPOINT ["executable", "param1", "param2"] // docker run参数追加模式
ENTRYPOINT command param1 param2 // docker run 参数替换模式
- docker run –entrypoint 可替换 Dockerfile 中定义的ENTRYPOINT
- ENTRYPOINT的最佳实践是用ENTRYPOINT定义镜像主命令,并通过CMD定义主要参数,如下所示
- ENTRYPOINT ["s3cmd"]
- CMD ["--help"]
Dockerfile 的最佳实践
- 不要安装无效软件包。
- 应简化镜像中同时运行的进程数,理想状况下,每个镜像应该只有一个进程。
- 当无法避免同一镜像运行多进程时,应选择合理的初始化进程(initprocess)。
- 最小化层级数
- 最新的docker只有RUN,COPY,ADD创建新层,其他指令创建临时层,不会增加镜像大小。
- 比如EXPOSE指令就不会生成新层。
- 多条RUN命令可通过连接符连接成一条指令集以减少层数。
- 通过多段构建减少镜像层数。
- 最新的docker只有RUN,COPY,ADD创建新层,其他指令创建临时层,不会增加镜像大小。
- 把多行参数按字母排序,可以减少可能出现的重复参数,并且提高可读性。
- 编写dockerfile的时候,应该把变更频率低的编译指令优先构建以便放在镜像底层以有效利用buildcache。
- 复制文件时,每个文件应独立复制,这确保某个文件变更时,只影响改文件对应的缓存。
Docker优势
- 封装性:
- 不需要再启动内核,所以应用扩缩容时可以秒速启动。
- 资源利用率高,直接使用宿主机内核调度资源,性能损失 小。
- 方便的CPU、内存资源调整。
- 能实现秒级快速回滚。
- 一键启动所有依赖服务,测试不用为搭建环境犯愁,PE也不用为 建站复杂担心。
- 镜像一次编译,随处使用。
- 测试、生产环境高度一致(数据除外)。
- 隔离性:
- 应用的运行环境和宿主机环境无关,完全由镜像控制,一台物理 机上部署多种环境的镜像测试。
- 多个应用版本可以并存在机器上。
- 镜像增量分发:
- 由于采用了Union FS,简单来说就是支持将不同的目录 挂载到同一个虚拟文件系统下,并实现一种layer的概 念,每次发布只传输变化的部分,节约带宽。

学习容器的概念,以及Dockerfile的编写
浙公网安备 33010602011771号