img

Introduction

软件开发最大的麻烦事之一,就是环境配置。用户计算机的环境不同,可能导致软件在开发环境中能运行,而到了生产环境无法运行的情况。

用户必须保证两件事:操作系统的设置,各种库和组件的安装。只有它们都正确,软件才能运行。举例来说,安装一个 Python 应用,计算机必须有 Python 引擎,还必须有各种依赖,可能还要配置环境变量。

环境配置如此麻烦,换一台机器,就要重来一次,旷日费时。很多人想到,能不能从根本上解决问题,软件可以带环境安装?也就是说,安装的时候,把原始环境一模一样地复制过来

这个问题的一种解决方式是使用虚拟机,比如我们常用的 WSL,就是在 Windows 系统中运行 Linux 虚拟系统的例子。但是,这样做的资源占用多,要重新配置一个全新操作系统的冗余步骤多,启动起来也十分缓慢。于是,Linux 发展出了另一种虚拟化技术:虚拟容器

Linux 容器不是模拟一个完整的操作系统,而是对进程进行隔离。或者说,在正常进程的外面套了一个保护层。对于容器里面的进程来说,它接触到的各种资源都是虚拟的,从而实现与底层系统的隔离。

Docker 属于 Linux 容器的一种封装,提供简单易用的容器使用接口。它是目前最流行的 Linux 容器解决方案。

Docker 将应用程序与该程序的依赖,打包在一个文件里面。运行这个文件,就会生成一个虚拟容器。程序在这个虚拟容器里运行,就好像在真实的物理机上运行一样。有了 Docker,就不用担心环境问题。

总体来说,Docker 的接口相当简单,用户可以方便地创建和使用容器,把自己的应用放入容器。容器还可以进行版本管理、复制、分享、修改,就像管理普通的代码一样。

Installation

Concepts

  1. 镜像(Image):类似于虚拟机中的镜像,是一个包含有文件系统的面向 Docker 引擎的只读模板。任何应用程序运行都需要环境,而镜像就是用来提供这种运行环境的。例如一个 Ubuntu 镜像就是一个包含 Ubuntu 操作系统环境的模板,同理在该镜像上装上 Apache 软件,就可以称为 Apache 镜像。
  2. 容器(Container):类似于一个轻量级的沙盒,可以将其看作一个极简的 Linux 系统环境(包括 root 权限、进程空间、用户空间和网络空间等),以及运行在其中的应用程序。Docker 引擎利用容器来运行、隔离各个应用。容器是镜像创建的应用实例,可以创建、启动、停止、删除容器,各个容器之间是是相互隔离的,互不影响。注意:镜像本身是只读的,容器从镜像启动时,Docker 在镜像的上层创建一个可写层,镜像本身不变。
  3. 仓库(Repository):类似于代码仓库,这里是镜像仓库,是 Docker 用来集中存放镜像文件的地方。注意与注册服务器(Registry)的区别:注册服务器是存放仓库的地方,一般会有多个仓库;而仓库是存放镜像的地方,一般每个仓库存放一类镜像,每个镜像利用 tag 进行区分,比如 Ubuntu 仓库存放有多个版本(12.04、14.04 等)的 Ubuntu 镜像。

Images

对镜像的基本操作总结:

  • 官方注册服务器(Registry):https://hub.docker.com/
  • 搜索某个镜像:docker search <image>
  • 将某个镜像下载到本地:
    • docker pull <image>// 如果不加 tag 默认使用 latest 镜像
    • docker pull <image>:<tag>
  • 查看当前下载的镜像信息:docker images
  • 新建自定义镜像的方法

方法 1:利用镜像启动一个容器后修改,再进行 commit

[root@xxx ~]# docker run -it centos:latest /bin/bash    # 启动一个容器
[root@72f1a8a0e394 /]#    # 这里命令行形式变了,表示已经进入了一个新环境
[root@72f1a8a0e394 /]# git --version    # 此时的容器中没有 git
bash: git: command not found
[root@72f1a8a0e394 /]# yum install git    # 利用 yum 安装 git
......
[root@72f1a8a0e394 /]# git --version   # 此时的容器中已经装有 git 了
git version 1.8.3.1

然后按下 Ctrl+D 或者输入 exit 退出容器,然后查看当前所有容器:docker ps -a。这里将容器转化为一个镜像,即执行 commit 操作,完成后可使用 docker images 查看:

[root@xxx ~]# docker ps -a
CONTAINER ID  IMAGE    COMMAND      CREATED   STATUS   PORTS    NAMES
72f1a8a0e394  centos:latest "/bin/bash"  9 minutes ago   Exited (0) 3 minutes ago      angry_hodgkin

[root@xxx ~]# docker commit -m "Commit Message" -a "UserInfo" <Container ID> <user>/<repo>:<tag>

[root@xxx ~]# docker images
REPOSITORY       TAG    IMAGE ID         CREATED             SIZE
<user>/<repo>    git    52166e4475ed     5 seconds ago       358.1 MB
centos           latest 0584b3d2cf6d     9 days ago          196.5 MB

此时 Docker 引擎中就有了我们新建的镜像 <user>/<repo>:<tag>,此镜像和原有的 CentOS 镜像区别在于多了个 Git 工具。此时我们利用新镜像创建的容器,本身就自带 Git 了。

方法 2:使用 Dockerfile

Dockerfile 可以理解为一种配置文件,用来告诉 docker build 命令应该执行哪些操作。一个简易的 Dockerfile 文件如下所示:

# 说明该镜像以哪个镜像为基础
FROM centos:latest

# 构建者的基本信息
MAINTAINER <user>

# 在 build 这个镜像时执行的操作 
RUN yum update
RUN yum install -y git

# 拷贝本地文件到镜像中
COPY ./* /usr/share/gitdir/

# Expose 对应端口,允许外部连接
EXPOSE 3000

官方教程链接:https://docs.docker.com/engine/reference/builder/

有了 Dockerfile 之后,就可以利用 build 命令构建镜像了:

[root@xxx ~]# docker build -t="<user>/<repo>:<tag>" .

其中 -t 用来指定新镜像的用户信息、tag 等。最后的点表示在当前目录寻找 Dockerfile

  • 删除容器或镜像

    • 删除容器:docker rm container_name/container_id
    • 删除镜像:docker rmi image_name/image_id
    • 删除镜像前必须先删除以此镜像为基础的容器。
  • 镜像的保存与加载

    • 保存镜像:docker save -o centos.tar <user>/<repo>:<tag>
    • 加载镜像:docker load -i centos.tar

Containers

  • 启动容器:docker run [Options] <Image> [Command]
    • -d:Run container in background and print container ID
    • -e:Set environment variables
    • -i:Keep STDIN open even if not attached
    • -p <host>:<container>:Publish a container’s port to the host
    • -t:Allocate a pseudo-TTY
    • --name:Assign a name to the container
    • -v <host>:<container>:Mount host_path to container_path
    • 常用命令:docker run -itd centos:latest /bin/bash
    • 如果想让容器一直运行,而不是停止,可以使用快捷键 Ctrl+P Ctrl+Q 退出,此时容器的状态为 Up。
  • 启动容器:docker start <container>
  • 停止容器:docker stop container>
  • 重启容器:docker restart <container>
  • 进入已启动的容器:docker attach <container>
  • 复制文件:docker cp <container>:<path> <host_path>

Repositories

  • 官方镜像服务器:https://hub.docker.com
  • 登录 DockerHub:docker login
  • 推送本地镜像:docker push <username>/<repo>:<tag>
    • username 必须与你 Docker Hub 中的用户名一致
  • 拉取远端镜像:docker pull <username>/<repo>:<tag>

参考链接