Docker 最初是 dotCloud 公司创始人 Solomon Hykes 在法国期间发起的一个公司内部项目,它是基于 dotCloud 公司多年云服务技术的一次革新,并于 2013 年 3 月以 Apache 2.0 授权协议开源,主要项目代码在 GitHub 上进行维护。

Docker 项目后来还加入了 Linux 基金会,并成立推动 开放容器联盟(OCI)。

由于 Docker 项目的火爆,在 2013 年底,dotCloud 公司决定改名为 Docker。

Docker 最初是在 Ubuntu 12.04 上开发实现的;Red Hat 则从 RHEL 6.5 开始对 Docker 进行支持;Google 也在其 PaaS 产品中广泛应用 Docker。

下面的图片比较了 Docker 和传统虚拟化方式的不同之处。传统虚拟机技术是虚拟出一套硬件后,在其上运行一个完整操作系统,在该系统上再运行所需应用进程;而容器内的应用进程直接运行于宿主的内核,容器内没有自己的内核,而且也没有进行硬件虚拟。因此容器要比传统虚拟机更为轻便。
图片.png

一、docker主要概念

1. 镜像

Docker 镜像 是一个特殊的文件系统,除了提供容器运行时所需的程序、库、资源、配置等文件外,还包含了一些为运行时准备的一些配置参数(如匿名卷、环境变量、用户等)。

镜像 不包含 任何动态数据,其内容在构建之后也不会被改变

分层存储

因为镜像包含操作系统完整的 root 文件系统,其体积往往是庞大的,因此在 Docker 设计时,就充分利用 Union FS 的技术,将其设计为分层存储的架构

2. 容器

镜像(Image)和容器(Container)的关系,就像是面向对象程序设计中的 类 和 实例 一样,镜像是静态的定义,容器是镜像运行时的实体。容器可以被创建、启动、停止、删除、暂停等。

容器的实质是进程,容器进程运行于属于自己的独立的 命名空间。因此容器可以拥有自己的 root 文件系统、自己的网络配置、自己的进程空间,甚至自己的用户 ID 空间。容器内的进程是运行在一个隔离的环境里,使用起来,就好像是在一个独立于宿主的系统下操作一样。这种特性使得容器封装的应用比直接在宿主运行更加安全。

3. 仓库

镜像构建完成后,可以很容易的在当前宿主机上运行,但是,如果需要在其它服务器上使用这个镜像,我们就需要一个集中的存储、分发镜像的服务,Docker Registry 就是这样的服务。

一个 Docker Registry 中可以包含多个 仓库(Repository);每个仓库可以包含多个 标签(Tag);每个标签对应一个镜像。

Docker Registry 公开服务

最常使用的 Registry 公开服务是官方的 Docker Hub

私有 Docker Registry

除了使用公开服务外,用户还可以在本地搭建私有 Docker Registry。Docker 官方提供了 Docker Registry 镜像,可以直接使用做为私有 Registry 服务。在 私有仓库 一节中,会有进一步的搭建私有 Registry 服务的讲解。

开源的 Docker Registry 镜像只提供了 Docker Registry API 的服务端实现,足以支持 docker 命令,不影响使用。但不包含图形界面,以及镜像维护、用户管理、访问控制等高级功能。

除了官方的 Docker Registry 外,还有第三方软件实现了 Docker Registry API,甚至提供了用户界面以及一些高级功能。比如,Harbor 和 Sonatype Nexus。

三、使用镜像

1. 下载镜像

docker pull [选项] [仓库地址[:端口号]/]仓库名[:标签]
  • 选项:可以通过 docker pull --help 命令看到
  • 仓库地址:地址的格式一般是 <域名/IP>[:端口号]。默认地址是 Docker Hub的地址:docker.io
  • 仓库名:是两段式名称,即 <用户名>/<软件名>。对于 Docker Hub,如果不给出用户名,则默认为 library,也就是官方镜像。

    $ docker pull nginx
    $ docker pull docker.io/library/nginx:latest
    
    latest: Pulling from library/nginx
    Digest: sha256:2275af0f20d71b293916f1958f8497f987b8d8fd8113df54635f2a5915002bf1
    Status: Image is up to date for nginx:latest
    docker.io/library/nginx:latest

2. 运行镜像(容器)

有了镜像后,我们就能够以这个镜像为基础启动并运行一个容器。

$ docker run -it --rm ubuntu:18.04 bash

root@e7009c6ce357:/# cat /etc/os-release
NAME="Ubuntu"
VERSION="18.04.1 LTS (Bionic Beaver)"
ID=ubuntu
ID_LIKE=debian
PRETTY_NAME="Ubuntu 18.04.1 LTS"
VERSION_ID="18.04"
HOME_URL="https://www.ubuntu.com/"
SUPPORT_URL="https://help.ubuntu.com/"
BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
VERSION_CODENAME=bionic
UBUNTU_CODENAME=bionic

3. 列出镜像

docker image ls [OPTIONS] [REPOSITORY[:TAG]]

4. 删除镜像

docker image rm [OPTIONS] IMAGE [IMAGE...]
$ docker image rm 1276

Untagged: nginx:latest
Untagged: nginx@sha256:2275af0f20d71b293916f1958f8497f987b8d8fd8113df54635f2a5915002bf1
Deleted: sha256:12766a6745eea133de9fdcd03ff720fa971fdaf21113d4bc72b417c123b15619
Deleted: sha256:3ea962f6f388096ab9798790d363fc6f9c779c924a5eddf5c699d8da080114f7
Deleted: sha256:091a2aef7242e42505b69f1ad027d6a442cfce2403e260ac914f0fd6cc2d275f
Deleted: sha256:4e72a31f1cd6fd655cc0826c91e886967b6e965e13ac21f31f9f66c27a3b7732
Deleted: sha256:e3d1cdf9772a260b3e81a22c1940d63ac45dfe67720f78f00ca73834d9498934
Deleted: sha256:af40da71a8618ea9cbcdc333d5e60bd5b6df820f0d07a55f7c9a1c21fd930095
Deleted: sha256:608f3a074261105f129d707e4d9ad3d41b5baa94887f092b7c2857f7274a2fce

四、操作容器

1. 启动容器

启动容器有两种方式:

  • 新建并启动:基于镜像新建一个容器并启动
  • 启动已终止容器:将在终止状态(exited)的容器重新启动

1.1 新建并启动

docker run [OPTIONS] IMAGE [COMMAND] [ARG...]
$ docker run ubuntu echo 'Hello world'
Hello world

这跟在本地直接执行 echo 'hello world' 几乎感觉不出任何区别。

下面的命令则启动一个 bash 终端,允许用户进行交互(其实默认就是执行bash)

$ docker run -it ubuntu /bin/bash
root@af8bae53bdd3:/#

当利用 docker run 来创建容器时,Docker 在后台运行的标准操作包括:

  • 检查本地是否存在指定的镜像,不存在就从 registry 下载
  • 利用镜像创建并启动一个容器
  • 分配一个文件系统,并在只读的镜像层外面挂载一层可读写层
  • 从宿主主机配置的网桥接口中桥接一个虚拟接口到容器中去
  • 从地址池配置一个 ip 地址给容器
  • 执行用户指定的应用程序
  • 执行完毕后容器被终止
守护状态运行

需要让 Docker 在后台运行而不是直接把执行命令的结果输出在当前宿主机下。此时,可以通过添加 -d 参数来实现

1.2 启动已终止容器

docker container start [OPTIONS] CONTAINER [CONTAINER...]

-a, --attach               Attach STDOUT/STDERR and forward signals
      --detach-keys string   Override the key sequence for detaching a container
-i, --interactive          Attach container's STDIN
查看容器日志
docker container logs [OPTIONS] CONTAINER

2. 终止和重启容器

终止容器:

docker container stop [OPTIONS] CONTAINER [CONTAINER...]

重启容器

docker container restart [OPTIONS] CONTAINER [CONTAINER...]

3. 进入容器

在使用 -d 参数时,容器启动后会进入后台。但某些时候需要进入容器进行操作

进入容器可以使用 docker attach 命令或 docker exec 命令

推荐大家使用 docker exec 命令,原因会在下面说明。

3.1 docker attach

docker attach [OPTIONS] CONTAINER

注意:如果从这个 stdin 中 exit,会导致容器的停止

3.2 docker exec

docker exec [OPTIONS] CONTAINER COMMAND [ARG...]
docker exec -it f2a487528d5e bash
root@f2a487528d5e:/# 

4. 导入和导出

4.1 导出容器

Usage:  docker export [OPTIONS] CONTAINER

Export a container's filesystem as a tar archive
$ docker export 8cf0 -o nginx-bak

$ docker export 8cf0 > nginx-bak

4.2 导入容器

docker import [OPTIONS] file|URL|- [REPOSITORY[:TAG]]

Import the contents from a tarball to create a filesystem image
$ docker import nginx-bak lihaixing/nginx:1

$ docker import http://example.com/exampleimage.tgz example/imagerepo

$ docker image ls

5. 删除容器

docker container rm [OPTIONS] CONTAINER [CONTAINER...]

-f, --force     Force the removal of a running container (uses SIGKILL)
-l, --link      Remove the specified link
-v, --volumes   Remove anonymous volumes associated with the container

清理所有终止的容器

docker container prune [OPTIONS]

Options:
  --filter filter   Provide filter values (e.g. 'until=<timestamp>')
  -f, --force           Do not prompt for confirmation

五、仓库

仓库(Repository)是集中存放镜像的地方。

  • 一个容易混淆的概念是注册服务器(Registry)。
  • 实际上注册服务器是管理仓库的具体服务器,每个服务器上可以有多个仓库,而每个仓库下面有多个镜像。
  • 从这方面来说,仓库可以被认为是一个具体的项目或目录。
  • 例如对于仓库地址 docker.io/ubuntu 来说,docker.io 是注册服务器地址,ubuntu 是仓库名。

1. 公共仓库 Docker Hub

1.1  注册

你可以在 https://hub.docker.com 免费注册一个 Docker 账号。

1.2 登录

可以通过执行 docker login 命令交互式的输入用户名及密码来完成在命令行界面登录 Docker Hub。

你可以通过 docker logout 退出登录。

1.3 拉取镜像

搜索镜像:docker search [OPTIONS] TERM

拉取镜像:docker pull [OPTIONS] NAME[:TAG|@DIGEST]

1.4 推送镜像

docker push [OPTIONS] NAME[:TAG]
  1. 私有仓库
    https://yeasy.gitbook.io/dock...

六、使用网络

1. 外部访问容器

容器中可以运行一些网络应用,要让外部也可以访问这些应用,可以通过 -P 或 -p 参数来指定端口映射。

  • -P 标记时,Docker 会随机映射一个端口到内部容器开放的网络端口。

    $ docker run -d -P nginx
    
    $ docker container ls
    CONTAINER ID   IMAGE     COMMAND                  CREATED         STATUS         PORTS                   NAMES
    c8c0db6fb216   nginx     "/docker-entrypoint.…"   9 seconds ago   Up 8 seconds   0.0.0.0:55000->80/tcp   gracious_elbakyan
    8cf0fda42738   nginx     "/docker-entrypoint.…"   12 hours ago    Up 12 hours    80/tcp                  vibrant_keller
    
    curl 0.0.0.0:55000
  • -p 则可以指定要映射的端口,并且,在一个指定端口上只可以绑定一个容器。支持的格式有 ip:hostPort:containerPort | ip::containerPort | hostPort:containerPort。

    $ docker run -d -p 80:80 nginx
    
    // 指定多个端口映射
    $ docker run -d \
      -p 80:80 \
      -p 443:443 \
      nginx
  • 查看端口

    $ docker port f3d
    80/tcp -> 0.0.0.0:80
    
    $ docker port f3d 80
    0.0.0.0:80

    2. 容器互联

    如果你之前有 Docker 使用经验,你可能已经习惯了使用 --link 参数来使容器互联。

随着 Docker 网络的完善,强烈建议大家将容器加入自定义的 Docker 网络来连接多个容器,而不是使用 --link 参数

2.1 新建网络

docker network COMMAND

Commands:
  connect     Connect a container to a network
  create      Create a network
  disconnect  Disconnect a container from a network
  inspect     Display detailed information on one or more networks
  ls          List networks
  prune       Remove all unused networks
  rm          Remove one or more networks
docker network create [OPTIONS] NETWORK

$ docker network create -d bridge my-net

-d 参数指定 Docker 网络类型,有 bridge overlay

2.2 连接容器

$ docker run -it --rm --name busybox1 --network my-net busybox

$ docker run -it --rm --name busybox2 --network my-net busybox

$ ping busybox1

lihaixing
463 声望719 粉丝

前端就爱瞎折腾