文章

Docker

Docker是什么

Docker 是一个开源的应用容器引擎,其中包括镜像、容器、仓库等功能,目的就是通过对应用组件的封装、分发、部署、运行等生命周期的管理,使用户的程序及其环境能够做到“一次封装,到处运行”。Docker实际上就相当于一个集装箱,它可以把不同的应用全都放在它的集装箱里面,并且以后有需要的时候,可以直接把集装箱搬到其他平台或者服务器上。残酷的是相比于容器本身,更有价值的是容器编排

隔离与限制

容器里运行的进程实际上运行在宿主机的操作系统上,但Docker通过Linux命名空间和cgroups机制实现了容器内进程与其他进程的隔离。

Linux命名空间隔离进程

默认情况下,每个linux系统最初仅有一个命名空间。所有系统资源属于这一个命名空间。但是你能创建额外的命名空间,以及在他们之间组织资源。在一个命名空间中,运行一个进程,该进程将只能看到同一个命名空间下的资源。当然,会存在所种类型的多个命名空间,所以一个进程不单单只属于一个命名空间,而属于每个类型的一个命名空间。 存在以下类型的命名空间:

  • Mount
  • Process ID
  • Network
  • Inter-process communicaion
  • UTS(主机、域名)
  • User ID

限制进程的可用资源

cgroups是一个Liux内核功能,它被用来限制一个进程或一组进程的资源使用。一个进程的资源(cpu,内存,网络带宽等)使用量不通超出被分配的量。这种方式下,进程不能过分使用为其他进程保留的资源。

可移植性的限制

理论上,一个容器镜像能运行在任何一个运行Docker的容器上,但如果一个容器化的应用需要一个特定的内核版本,那么它可能不能在每台机器上都工作,如果一台机器上运行了一个不匹配的内核版本,或者没有相同的内核模块可用,那么此应用就不能在其上运行。

镜像分层

Docker镜像基于联合文件系统(Union FS)技术,实现镜像分层和写时拷贝。

Docker镜像由多层构成。不同镜像可以包含完全相同的层,位于这些镜像都是基于另一个镜像之上构建的,不同的镜像都能使用相同的父镜像作为他们的基础镜像,这提升了镜像在网络上的分发效率,同时也减少了镜像的存储空间。当基于相同基础层的镜像被构建成两个容器时,它们就能够读相同的文件。但是如果其中一个容器写入某些文件,另外一个是无法看见文件变更的。因此即使它们共享文件,仍然彼此隔离。这是因为容器镜像层是只读的。容器运行时,一个新的可写层在镜像层之上被创建。容器修改位于底层的一个文件时,此文件的一个拷贝在顶层被创建,进程写的是此拷贝。

Dockerfile

Dockerfile 是一个用来构建镜像的文本文件,文本内容包含了一条条构建镜像所需的指令和说明。

命令说明

  • FROM:构建镜像基于哪个镜像
  • MAINTAINER:镜像维护者姓名或邮箱地址
  • RUN:构建镜像时运行的指令
  • CMD:运行容器时执行的shell环境
  • VOLUME:指定容器挂载点到宿主机自动生成的目录或其他容器
  • USER:为RUN、CMD、和 ENTRYPOINT 执行命令指定运行用户
  • WORKDIR:为 RUN、CMD、ENTRYPOINT、COPY 和 ADD 设置工作目录,就是切换目录
  • ARG:构建时指定的一些参数
  • EXPOSE:声明容器的服务端口(仅仅是声明)
  • ENV:设置容器环境变量
  • ADD:拷贝文件或目录到容器中,如果是URL或压缩包便会自动下载或自动解压
  • COPY:拷贝文件或目录到容器中,跟ADD类似,但不具备自动下载或解压的功能
  • ENTRYPOINT:运行容器时执行的shell命令

基础命令

镜像仓库

登录

1
docker login -u username -p password server 

登出

1
docker logout 

查看镜像列表

1
docker images

删除镜像

1
docker rmi <image_id>

拉取镜像

1
docker pull <repository>/<image_name>:tag

推送镜像

1
docker push <repository>/<image_name>:tag

更新镜像

1
docker commit -m 'commit desc' -a 'author' <container_id> <repository>/<image_name>:tag

构建镜像

1
docker build -t <repository>/<image_name>:tag .

设置镜像标签

1
docker tag imageId <repository>/<image_name>:tag

容器

查看容器列表

1
2
3
4
5
docker ps
# -a 查看所有容器
# -s 查看容器大小
# -q 仅查看容器Id
# -l 查看最后一个容器

删除容器

1
docker rm <container_id>

查看容器详细信息

1
docker inspect <container_id>

查看容器日志

1
2
3
docker logs <container_id>
# 容器日志在主机中的路径
# /var/lib/docker/containers/<container_id>/<container_id>-json.log

运行容器

1
2
3
4
5
6
7
8
9
10
docker run -d --name containerName <repository>/<image_name>:tag
# -P : 容器内部端口随机映射到主机的端口
# -p : 容器内部端口绑定到指定的主机端口
# -v : 将容器内部数据卷映射到主机数据卷
# --cpus 2 限制容器可以使用的cpu核数
# --cpuset-cpus "1,3" 限制容器运行在指定的cpu(1,3)核心上
# --cpu-shares 1024 限制每个容器能使用的cpu时间权重,默认1024 
# -m或--memory 200M 设置内存的使用限额
# --memory-swap:设置内存+swap的使用限额。
# --blkio-weight 600 设置容器读写磁盘带宽的权重,默认500

重启容器

1
docker restart <container_id>

关闭容器

1
docker stop <container_id>

进入容器

1
docker exec -it <container_id> /bin/bash

导出容器

1
docker export <container_id> res.tar

导入容器

1
cat docker/res.tar | docker import - test/ubuntu:v1

导出镜像

1
docker save -o myimage.tar myimage:latest

导入镜像

1
docker load -i myimage.tar
本文由作者按照 CC BY 4.0 进行授权