Docker是一个容器化平台,它将应用程序及其所有依赖项以容器的形式打包在一起,以确保应用程序在任何环境(无论是开发环境、测试环境还是生产环境)中无缝运行。
常用命令
镜像操作
- 列出本地镜像
docker images
- 获取镜像
docker pull mysql
- 搜索镜像
docker search mysql
- 删除镜像
docker rmi -f mysql
- 编写Dockerfile
#在centos上安装nginx
FROM centos
#标明著作人的名称和邮箱
MAINTAINER jiabuli 649917837@qq.com
#测试一下网络环境
RUN ping -c 1 www.baidu.com
#安装nginx必要的一些软件
RUN yum -y install gcc make pcre-devel zlib-devel tar zlib
#把nginx安装包复制到/usr/src/目录下
ADD nginx-1.15.8.tar.gz /usr/src/
#切换到/usr/src/nginx-1.15.8编译并且安装nginx
RUN cd /usr/src/nginx-1.15.8 \
&& mkdir /usr/local/nginx \
&& ./configure --prefix=/usr/local/nginx && make && make install \
&& ln -s /usr/local/nginx/sbin/nginx /usr/local/sbin/ \
&& nginx
#删除安装nginx安装目录
RUN rm -rf /usr/src/nginx-nginx-1.15.8
#对外暴露80端口
EXPOSE 80
#启动nginx
CMD ["nginx", "-g", "daemon off;"]
- 构建镜像
docker build -f /docker/dockerfile/nginx -t nginx:1.15.8
容器操作
- 启动容器
docker run -i -t --name mysentos
参数说明:
-i:交互式操作
-t:终端
—name:为容器指定名字
- 启动已停止的容器
docker start/restart mysql
- 查看容器
docker ps
- 停止容器
docker stop/kill/(rm -f) mysql
- 生成镜像
docker commit -a="lamarsan" -m="my mysql" [容器ID] mysql:5.7
参数说明:
-a:镜像作者
-c:用Dockerfile指令来创建镜像
-m:说明
-p:在commit时,将容器暂停
Docker组成
镜像、容器、仓库。
镜像
Docker 镜像(Image)就是一个只读的模板。镜像可以用来创建 Docker 容器,一个镜像可以创建很多容器。
镜像由一系列只读层构建,所谓的层代表着镜像Dockerfile中的一条指令。
容器
- Docker 利用容器(Container)独立运行的一个或一组应用。容器是用镜像创建的运行实例。
- 它可以被启动、开始、停止、删除。每个容器都是相互隔离的、保证安全的平台。
- 可以把容器看做是一个简易版的 Linux 环境(包括root用户权限、进程空间、用户空间和网络空间等)和运行在其中的应用程序。
- 容器的定义和镜像几乎一模一样,也是一堆层的统一视角,唯一区别在于容器的最上面那一层是可读可写的。
仓库
仓库是集中存放镜像文件的场所。
仓库分为公开仓库(Public)和私有仓库(Private)两种形式。最大的公开仓库是 Docker Hub,存放了数量庞大的镜像供用户下载。国内的公开仓库包括阿里云 、网易云 等。
Docker Compose
Docker Compose是 docker 提供的一个命令行工具,用来定义和运行由多个容器组成的应用。使用 compose,我们可以通过 YAML 文件声明式的定义应用程序的各个服务,并由单个命令完成应用的创建和启动。
使用步骤如下:
- 定义应用环境,
Dockerfile
以便可以在任何地方复制。 - 定义组成应用程序的服务,
docker-compose.yml
以便它们可以在隔离的环境中一起运行。 - Run
docker-compose up
and Compose启动并运行您的整个应用程序。
docker-compose.yml
这是Docker Compose运行时所需的配置文件:
version: '3'
services:
# 定义web服务
web:
# 文件地址
build: .
# 开放端口
ports:
- "5000:5000"
# 卷挂载路径设置
volumes:
- .:/code
- logvolume01:/var/log
links:
- redis
# 定义redis服务
redis:
image: redis
volumes:
logvolume01: {}
编写完成后使用docker-compose up -d
进行运行。该web
服务使用从Dockerfile
当前目录中构建的映像。然后,它将容器和主机绑定到暴露的端口5000
。
常见命令
- 执行命令运行容器
docker-compose up -d
- 查看镜像
docker images
- 停止和删除容器
docker-compose stop/rm redis
DockerFile常见指令
- FROM:指定基础镜像
- LABEL:功能是为镜像指定标签
- RUN:运行指定的命令
- CMD:容器启动时要运行的命令
Docker Swarm
Docker Swarm是Docker的本机群集。它将Docker主机池转变为单个虚拟Docker主机。Docker Swarm提供标准的Docker API,任何已经与Docker守护进程通信的工具都可以使用Swarm透明地扩展到多个主机。
Docker容器的几种状态
- 运行
- 已暂停
- 重新启动
- 已退出
可以通过运行命令来识别Docker容器的状态:
Docker实现原理
docker依靠linux的NameSpace与CGroup实现。
NameSpace
在 linux 启动的时候又一个 pid 为1的 init 进程,其他所有的进程都由此进程衍生而来,init 和其他衍生而来的进程形成以 init 进程为根节点树状结构,在同一个进程树里的进程只要有足够的权限就可以审查甚至终止其他进程。
这样,显然会带来安全性问题。而 pid namespace(linux namespace 的一种)允许我们创建单独的进程树,新进程树里面有自己的 pid 为1的进程,该进程一般为创建新进程树的时候指定。pid namespace 使得不同进程树里面的进程不能相互直接访问,提供了进程间的隔离,甚至可以创建嵌套的进程树:
PID,IPC,Network等系统资源不再是全局性的,而是属于某个特定的Namespace。每个namespace下的资源对于其他namespace下的资源都是透明,不可见的。因此在操作系统层面上看,就会出现多个相同pid的进程。系统中可以同时存在两个进程号为0,1,2的进程,由于属于不同的namespace,所以它们之间并不冲突。而在用户层面上只能看到属于用户自己namespace下的资源,例如使用ps命令只能列出自己namespace下的进程。这样每个namespace看上去就像一个单独的Linux系统。
CGroups
Docker 容器使用 linux namespace 来隔离其运行环境,使得容器中的进程看起来就像一个独立环境中运行一样。但是,光有运行环境隔离还不够,因为这些进程还是可以不受限制地使用系统资源,比如网络、磁盘、CPU以及内存 等。关于其目的,一方面,是为了防止它占用了太多的资源而影响到其它进程;另一方面,在系统资源耗尽的时候,linux 内核会触发 OOM,这会让一些被杀掉的进程成了无辜的替死鬼。因此,为了让容器中的进程更加可控,Docker 使用 Linux cgroups 来限制容器中的进程允许使用的系统资源。
Linux Cgroup 可为系统中所运行任务(进程)的用户定义组群分配资源 — 比如 CPU 时间、系统内存、网络带宽或者这些资源的组合。可以监控管理员配置的 cgroup,拒绝 cgroup 访问某些资源,甚至在运行的系统中动态配置 cgroup。所以,可以将 controll groups 理解为 controller (system resource) (for) (process)groups,也就是是说它以一组进程为目标进行系统资源分配和控制。它主要提供了如下功能:
Resource limitation: 限制资源使用,比如内存使用上限以及文件系统的缓存限制。
Prioritization: 优先级控制,比如:CPU利用和磁盘IO吞吐。
Accounting: 一些审计或一些统计,主要目的是为了计费。
Controll: 挂起进程,恢复执行进程。使用 cgroup,系统管理员可更具体地控制对系统资源的分配、优先顺序、拒绝、管理和监控。可更好地根据任务和用户分配硬件资源,提高总体效率。
在实践中,系统管理员一般会利用CGroup做下面这些事:
- 隔离一个进程集合(比如:nginx的所有进程),并限制他们所消费的资源,比如绑定CPU的核。
- 为这组进程分配其足够使用的内存
- 为这组进程分配相应的网络带宽和磁盘存储限制
- 限制访问某些设备(通过设置设备的白名单)
Docker实现
Docker 通过为每一个容器创建 namespace 和 cgroup 的组合来实现隔离:
除了需要挂载宿主机的文件系统以及与宿主机做端口映射之外,每个容器实际上都是独立的 namespace 和 cgroup 的组合。但是,通过 docker 提供的一些命令行参数,我们完全可以让多个容器共享同一个 namespace,从而可以直接通信。Docker与虚拟机的区别
| 特性 | docker | kvm虚拟机 | | —- | —- | —- | | 启动速度 | 秒级 | 分钟级 | | 计算机消耗 | 几乎无 | 50%左右 | | 性能 | 接近原生 | 弱 | | 系统支持量 | 上千个 | 几万个 | | 隔离性 | 容器间相互隔离,与宿主机隔离 | 完全隔离 |