虚拟机和 docker 的区别,如下图:
Image (镜像)
镜像不包含任何动态数据,其内容在构建之后也不会被改变。镜像(Image)就是一堆只读层(read-only layer)的统一视角。
从左边我们看到了多个只读层,它们重叠在一起。除了最下面一层,其他层都会有一个指针指向下一层。这些层是 Docker 内部的实现细节,并且能够在主机的文件系统上访问到。
统一文件系统(Union File System)技术能够将不同的层整合成一个文件系统,为这些层提供了一个统一的视角。
这样就隐藏了多层的存在,在用户的角度看来,只存在一个文件系统。我们可以在图片的右边看到这个视角的形式。
Container (容器)
容器(Container)的定义和镜像(Image)几乎一模一样,也是一堆层的统一视角,唯一区别在于容器的最上面那一层是可读可写的。
由于容器的定义并没有提及是否要运行容器,所以实际上,容器 = 镜像 + 读写层。
Repository (仓库)
Docker 仓库是集中存放镜像文件的场所。镜像构建完成后,可以很容易的在当前宿主上运行。
如果需要在其他服务器上使用这个镜像,就需要一个集中的存储、分发镜像的服务,Docker Registry(仓库注册服务器)就是这样的服务。
通常,一个仓库会包含同一个软件不同版本的镜像,而标签就常用于对应该软件的各个版本 。
可以通过<仓库名>:<标签>的格式来指定具体是这个软件哪个版本的镜像。如果不给出标签,将以 Latest 作为默认标签。
仓库又可以分为两种形式:
- Public(公有仓库)
- Private(私有仓库)
Docker 架构
Docker 的核心组件包括:
- Docker Client
- Docker Daemon
- Docker Image
- Docker Registry
- Docker Container
Docker 采用的是 Client/Server 架构。客户端向服务器发送请求,服务器负责构建、运行和分发容器。
客户端和服务器可以运行在同一个 Host 上,客户端也可以通过 Socket 或 REST API 与远程的服务器通信。
Docker Client
Docker Client ,也称 Docker 客户端。它其实就是 Docker 提供命令行界面(CLI)工具,是许多 Docker 用户与 Docker 进行交互的主要方式。
客户端可以构建,运行和停止应用程序,还可以远程与 Docker_Host 进行交互。
最常用的 Docker 客户端就是 Docker 命令,我们可以通过 Docker 命令很方便地在 Host 上构建和运行 Docker 容器。
Docker Daemon
Docker Daemon 是服务器组件,以 Linux 后台服务的方式运行,是 Docker 最核心的后台进程,我们也把它称为守护进程。
它负责响应来自 Docker Client 的请求,然后将这些请求翻译成系统调用完成容器管理操作。
该进程会在后台启动一个 API Server ,负责接收由 Docker Client 发送的请求,接收到的请求将通过 Docker Daemon 内部的一个路由分发调度,由具体的函数来执行请求。
大致可以将其分为以下三部分:
- Docker Server
- Engine
- Job
Docker Daemon 可以认为是通过 Docker Server 模块接受 Docker Client 的请求,并在 Engine 中处理请求,然后根据请求类型,创建出指定的 Job 并运行。
Docker Daemon 运行在 Docker Host 上,负责创建、运行、监控容器,构建、存储镜像。
运行过程的作用有以下几种可能:
- 向 Docker Registry 获取镜像。
- 通过 graphdriver 执行容器镜像的本地化操作。
- 通过 networkdriver 执行容器网络环境的配置。
- 通过 execdriver 执行容器内部运行的执行工作。
默认配置下,Docker Daemon 只能响应来自本地 Host 的客户端请求。如果要允许远程客户端请求,需要在配置文件中打开 TCP 监听。
Docker Image
Docker 镜像可以看作是一个特殊的文件系统,除了提供容器运行时所需的程序、库、资源、配置等文件外,还包含了一些为运行时准备的一些配置参数(如匿名卷、环境变量、用户等)。
镜像不包含任何动态数据,其内容在构建之后也不会被改变。我们可将 Docker 镜像看成只读模板,通过它可以创建 Docker 容器。
镜像有多种生成方法:
- 从无到有开始创建镜像
- 下载并使用别人创建好的现成的镜像
- 在现有镜像上创建新的镜像
我们可以将镜像的内容和创建步骤描述在一个文本文件中,这个文件被称作 Dockerfile ,通过执行 docker build <docker-file>命令可以构建出 Docker 镜像。
Docker Registry
Docker Registry 是存储 Docker Image 的仓库,运行 docker push、docker pull、docker search 时,实际上是通过 Docker Daemon 与 Docker Registry 通信。
Docker Container
Docker 容器就是 Docker 镜像的运行实例,是真正运行项目程序、消耗系统资源、提供服务的地方。
Docker Container 提供了系统硬件环境,可以使用 Docker Images 这些制作好的系统盘,再加上我们所编写好的项目代码,Run 一下就可以提供服务啦。
Docker 常用命令
拉取一个 Docker 镜像:docker pull image_name
查看主机下存在多少镜像:docker images
当前有哪些容器在运行:docker ps -a
对一个容器进行启动,重启和停止:
- docker start container_name/container_id
- docker restart container_name/container_id
- docker stop container_name/container_id
进入到这个容器中:docker attach container_name/container_id
运行这个容器中的镜像并且调用镜像里面的 bash :docker run -t -i container_name/container_id /bin/bash
删除指定镜像:(停止这个容器,删除这个容器,删除这个镜像)
- docker stop container_name/container_id
- docker rm container_name/container_id
- docker rmi image_name
编写 Dockerfile
Dockerfile 是自动构建 Docker 镜像的配置文件,用户可以使用 Dockerfile 快速创建自定义的镜像。
一般来说,可以将 Dockerfile 分为四个部分:
- 基础镜像(父镜像)信息指令 FROM。
- 维护者信息指令 MAINTAINER。
- 镜像操作指令 RUN 、EVN 、ADD 和 WORKDIR 等。
- 容器启动指令 CMD 、ENTRYPOINT 和 USER 等。
FROM python:2.7
MAINTAINER author<author@163.com>
COPY . /app
WORKDIR /app
RUN pip install -r requirements.txt
EXPOSE 5000
ENTRYPOINT ["python"]
CMD ["app.py"]
可以分析一下上面这个过程:
- 从 Docker Hub 上 Pull 下 Python 2.7 的基础镜像。
- 显示维护者的信息。
- Copy 当前目录到容器中的 /App 目录下 复制本地主机的 <src> ( Dockerfile 所在目录的相对路径)到容器里 <dest>。
- 指定工作路径为 /App。
- 安装依赖包。
- 暴露 5000 端口。
- 启动 App。
FROM
FROM 是用于指定基础的 images ,一般格式为 FROM <image> or FORM <image>:<tag>。
MAINTAINER
MAINTAINER 是用于指定镜像创建者和联系方式,一般格式为 MAINTAINER <name>。
COPY
COPY 是用于复制本地主机的 <src> (为 Dockerfile 所在目录的相对路径)到容器中的 <dest>。
WORKDIR
WORKDIR 用于配合 RUN,CMD,ENTRYPOINT 命令设置当前工作路径。
RUN
RUN 用于容器内部执行命令。每个 RUN 命令相当于在原有的镜像基础上添加了一个改动层,原有的镜像不会有变化。一般格式为 RUN <command> 。
EXPOSE
EXPOSE 命令用来指定对外开放的端口。一般格式为 EXPOSE <port> [<port>...]。
ENTRYPOINT
ENTRYPOINT 可以让你的容器表现得像一个可执行程序一样。一个 Dockerfile 中只能有一个 ENTRYPOINT,如果有多个,则最后一个生效。
ENTRYPOINT 命令也有两种格式:
- ENTRYPOINT ["executable", "param1", "param2"] :推荐使用的 Exec 形式。
- ENTRYPOINT command param1 param2 :Shell 形式。
这里我们将 Python 镜像变成可执行的程序:ENTRYPOINT ["python"]
CMD
CMD 命令用于启动容器时默认执行的命令,CMD 命令可以包含可执行文件,也可以不包含可执行文件。
不包含可执行文件的情况下就要用 ENTRYPOINT 指定一个,然后 CMD 命令的参数就会作为 ENTRYPOINT 的参数。
CMD 命令有三种格式:
- CMD ["executable","param1","param2"]:推荐使用的 exec 形式。
- CMD ["param1","param2"]:无可执行程序形式。
- CMD command param1 param2:Shell 形式。
一个 Dockerfile 中只能有一个 CMD,如果有多个,则最后一个生效。而 CMD 的 Shell 形式默认调用 /bin/sh -c 执行命令。
CMD 命令会被 Docker 命令行传入的参数覆盖:docker run busybox /bin/echo Hello Docker 会把 CMD 里的命令覆盖。
这里我们启动 /app :CMD ["app.py"]
构建 Dockerfile
在 Dockerfile 文件所在目录执行:docker build -t store_name/image_name:v1 .
- -t 是为新镜像设置仓库和名称
- store_name为仓库名
- image_name为镜像名
- :v1 为标签(不添加为默认 latest )