DockerMetabase

Docker 学习笔记(一):基础概念与基本操

2020-02-03  本文已影响0人  小叶与小茶

这篇笔记分成四个部分:
1. Docker 容器是什么
2. Docker 容器与虚拟机技术的对比
3. Docker 容器的核心概念
4. Docker 容器的安装
5. Docker 容器的基本操作

一、Docker 容器是什么?

大部分普通的软件工程师对“容器”的认知,确实源于 Docker。但 Docker 其实是源于 LXC(Linux Container)容器技术。LXC 并不是新技术,是一种操作系统级的虚拟化技术。这种技术能够将单个操作系统管理的资源划分到独立的分组中,以便能更好的在孤立的组之间平衡资源的使用。同时,由于是基于内核级别的运行,因此并不需要模拟特殊的、复杂的硬件指令,这令容器技术更轻量,更简单。LXC 已经被集成了主流的 Linux 内核中,已经成为 Linux 系统容器技术事实上的标准

Docker 源于LXC,而进一步优化了 LXC 的使用体验。通过提供丰富的容器管理工具(如打包、分发、版本管理、移植等),避免用户对底层进行操作,降低了 LXC 的使用门槛,最终推动了容器技术被广泛应用。

Docker是什么

二、Docker 容器与虚拟机技术的对比

提到容器,就避不开和传统虚拟机技术进行对比,而且容器本身也是一种虚拟化技术。因此有必要先对虚拟化技术进行一定的了解。

虚拟化(Virtualization)是一种资源管理技术,是将计算机的各种实体资源,如处理器、内存、存储、网络等,予以抽象和转换后呈现出来,打破实体间不可切割的障碍,使用户可以用到比原本的组态更好的方式来应用这些资源。

虚拟化的核心是对资源进行抽象,目标往往是为了在同一个主机上运行多个系统或应用,从而提高资源的利用率,降低成本,方便管理。

主流的虚拟化技术可以分为如下几个类别:

那么,容器和传统虚拟机技术的差异是什么呢?

传统虚拟机技术如 VMware ,VisualBox 需要模拟出完整的服务器环境,每台虚拟机都需要拥有自己的操作系统,即 GuestOS,同时还包括必要的库文件和应用程序。而虚拟机一旦启动,预分配给它的资源将全部被占用。

而容器技术则和宿主机共享硬件资源及操作系统。每个容器不需要拥有自己的操作系统,只需要包含应用和依赖包,与其他容器共享内核,但在彼此独立的进程空间中运行。

下面这两幅图直观的反映出两者的区别。

第一幅图:容器引擎部署在裸金属服务器上

容器引擎部署在裸金属服务器上

第二幅图:容器引擎部署在虚拟机上

容器引擎部署在虚拟机上

目前,这两种部署方式在都是广泛存在的。

通过使用容器,可以更轻松打包应用程序的代码、配置和依赖关系,将其变成容易使用的构建块,从而实现环境一致性、运营效率、开发人员生产力和版本控制等诸多目标。容器能帮助应用程序快速、可靠、一致地部署,不受部署环境的影响,迁移更简单。同时,容器还赋予对资源更多的精细化控制能力,让基础设施效率更高。

比如,基于常见的 LAMP(Linux+Apach+MySQL+PHP)组合运维一个网站,传统的做法是在虚拟机或物理机的操作系统上,单独安装 Apache、MySQL、PHP 以及它们的依赖环境,并进行复杂的配置和测试。这个过程可以参见我之前写过的一篇文章(LAMP开发环境搭建日志)。经历过,才知道坑有多深(当然,在传统方式下,通过XAMPP也是另一种简化的部署方案)。但通过容器打包 LAMP 的方案则聪明、轻量的多。后面也会写一篇实战的笔记,更直观的体验两种方式的差异。但不管怎样,自己都不再会再把时间花费在独自安装各个组件的事情上了。

曾经掉过的坑

所以,容器技术受到了广大开发和运维人员的喜爱,能够给大家带来很多实际的好处:

  1. 更快速的交付和部署。显而易见,容器更容易构建一套标准统一的环境,研发和运维人员可以使用同相同的环境来部署应用。所以在 DevOps 领域,容器是明星技术。
  2. 更高效的资源利用。容器不需要 GuestOS,这使得资源占用就具备很大优势了。而且由于容器共享宿主机(HostOS)的内核空间,理论上能够获得更高的执行效率
  3. 更轻松的迁移和扩展。Docker 容器几乎可以在各种基础设施平台上运行,只需要该平台上部署了 Docker Engine。比如物理机、虚拟机、公有云、私有云、混合云等等。
  4. 更简单的更新管理。这主要是指基于 Dockerfile 的自动化部署与软件管理方式。

Docker 容器作为一种轻量级的虚拟化技术,和传统虚拟机技术的特性差异如下表所示:

特性 容器 虚拟机
启动速度 秒级 分钟级
存储占用 MB级 GB级
性能对比 接近原生级别 理论达不到原生级别
系统量级 单机可支持上千个 单机支持几十个
安全能力 依赖宿主系统安全能力 完全隔离

单独提一下容器被广泛诟病的安全问题。传统虚拟机技术利用完全模拟或 Intel 的 VT-d 和 VT-x 的 ring-1 硬件隔离技术将物理资源完全进行隔离,不同的虚拟机即使底层运行在同一台物理主机上,彼此之间是完全独立的,在技术上能够实现虚拟机突破和彼此交互的防护。而 Docker 利用的只是 Linux 系统自身的进程空间隔离机制实现容器间的隔离,Docker 租户的 root 和宿主机的 HostOS 的 root 是等同的,也就是说,Docker 的特权租户可以直接对宿主机进行无限制操作,这相对虚拟机机制确实存在较大的安全隐患。目前,Docker 也引入了相应的安全选项和镜像签名机制,较大的改善了容器的安全能力。

Docker vs Virtual Machine

三、Docker 容器的核心概念

Docker 有三个核心概念:

  1. 镜像(Image)
  2. 容器(Container)
  3. 仓库(Repository)

理解了这三个核心概念,对于理解 Docker 整个生命周期会很有帮助。下面是一张被多次引用的图,清晰的描述了 Docker 的生命周期。

Docker生命周期
核心概念1:镜像

Docker 镜像(Image)和虚拟机镜像的概念是一样的,可以将其理解为一个面向 Docker 引擎的只读模板,可用于批量创造可运行的容器实例。Docker 镜像可以看作是一个特殊的文件系统,除了提供容器运行时所需的程序、库、资源、配置等文件外,还包含了一些为运行时准备的一些配置参数(如环境变量、用户等)。镜像不包含任何动态数据,其内容在构建之后也不会被改变。镜像是创建 Docker 容器的基础,而 Docker 体系能够提供一套简单的机制创建和更新已有的镜像,也可以从网上下载一个制作好的现成的镜像。

核心概念2:容器

Docker 容器(Container)是一个运行时的概念,可以理解为一个简易的 Linux 系统环境(包括 root 用户权限、进程空间、网络空间等概念)以及运行在其中的应用程序。每个 Docker 容器本质上就是一个 Linux 进程,拥有自己的上下文环境,彼此隔离。Docker 引擎能够对一个容器进行启动、停止、删除等操作。

核心概念3:仓库

Docker 仓库(Reopsitory)类似代码仓库,是 Docker 体系集中存放镜像文件的场所。一般情况下,一个仓库会包含同一个软件不同版本的镜像,用“标签”的概念来标记版本 。可以通过<仓库名>:<标签>的格式来精确定位具体采用哪个镜像。如果不指定标签,则采用 latest 作为默认标签。

根据存储的镜像公开与否,可以分为公开仓库(Public)和私有仓库(Private),目前最大的公开仓库是 Docker Hub,用户可以在自己的本地网络中创建私有仓库。

Docker 利用仓库管理镜像的理念类似于 Git,默认情况下 Docker 会在中央仓库(Docker Hub 和 Docker Cloud)寻找镜像文件。

Docker 基本架构

Docker 采用 C/S 架构。 Docker Server 负责构建、运行和分发 Docker 镜像。 Docker Client 和 Docker Server 可以运行在同一台机器上,也可以通过 RESTful 或其他网络接口进行远程通信,如下图所示:

Docker基本架构

从上图能够看到,Docker 体系的核心组件包括如下几部分:

1) Docker Client

Docker Client 提供了命令行界面 (CLI) ,是用户与 Docker 进行交互的主要窗口。通过 Client 可以构建、运行和停止容器,还可以与远程的 Docker Server 进行交互。

andy-zhang@localhost:~$ sudo docker
[sudo] password for andy-zhang: 

Usage:  docker [OPTIONS] COMMAND

A self-sufficient runtime for containers

Options:
      --config string      Location of client config files (default "/home/andy-zhang/.docker")
  -c, --context string     Name of the context to use to connect to the daemon (overrides DOCKER_HOST env var and default
                           context set with "docker context use")
  -D, --debug              Enable debug mode
  -H, --host list          Daemon socket(s) to connect to
  -l, --log-level string   Set the logging level ("debug"|"info"|"warn"|"error"|"fatal") (default "info")
      --tls                Use TLS; implied by --tlsverify
      --tlscacert string   Trust certs signed only by this CA (default "/home/andy-zhang/.docker/ca.pem")
      --tlscert string     Path to TLS certificate file (default "/home/andy-zhang/.docker/cert.pem")
      --tlskey string      Path to TLS key file (default "/home/andy-zhang/.docker/key.pem")
      --tlsverify          Use TLS and verify the remote
  -v, --version            Print version information and quit

Management Commands:
  builder     Manage builds
  config      Manage Docker configs
  container   Manage containers
  context     Manage contexts
  engine      Manage the docker engine
  image       Manage images
  network     Manage networks
  node        Manage Swarm nodes
  plugin      Manage plugins
  secret      Manage Docker secrets
  service     Manage services
  stack       Manage Docker stacks
  swarm       Manage Swarm
  system      Manage Docker
  trust       Manage trust on Docker images
  volume      Manage volumes

Commands:
  attach      Attach local standard input, output, and error streams to a running container
  build       Build an image from a Dockerfile
  commit      Create a new image from a container's changes
  cp          Copy files/folders between a container and the local filesystem
  create      Create a new container
  diff        Inspect changes to files or directories on a container's filesystem
  events      Get real time events from the server
  exec        Run a command in a running container
  export      Export a container's filesystem as a tar archive
  history     Show the history of an image
  images      List images
  import      Import the contents from a tarball to create a filesystem image
  info        Display system-wide information
  inspect     Return low-level information on Docker objects
  kill        Kill one or more running containers
  load        Load an image from a tar archive or STDIN
  login       Log in to a Docker registry
  logout      Log out from a Docker registry
  logs        Fetch the logs of a container
  pause       Pause all processes within one or more containers
  port        List port mappings or a specific mapping for the container
  ps          List containers
  pull        Pull an image or a repository from a registry
  push        Push an image or a repository to a registry
  rename      Rename a container
  restart     Restart one or more containers
  rm          Remove one or more containers
  rmi         Remove one or more images
  run         Run a command in a new container
  save        Save one or more images to a tar archive (streamed to STDOUT by default)
  search      Search the Docker Hub for images
  start       Start one or more stopped containers
  stats       Display a live stream of container(s) resource usage statistics
  stop        Stop one or more running containers
  tag         Create a tag TARGET_IMAGE that refers to SOURCE_IMAGE
  top         Display the running processes of a container
  unpause     Unpause all processes within one or more containers
  update      Update configuration of one or more containers
  version     Show the Docker version information
  wait        Block until one or more containers stop, then print their exit codes

2) Docker Daemon

Docker Daemon 是最核心的后台服务进程,以 Linux 后台服务的方式运行,也称为守护进程。它负责响应来自 Docker Client 的请求,内部对请求进行路由分发,交给具体的管理模块进行处理。

Docker Daemon逻辑架构

默认情况下,Docker Daemon 只能接收本地 Docker Client 的请求。如果要处理远程 Client 的请求,需要在配置文件中打开 TCP 监听

# 编辑 Docker 配置文件
andy-zhang@localhost:~$ vim.tiny /etc/systemd/system/multi-user.target.wants/docker.service

[Service]
Type=notify
# the default is not to use systemd for cgroups because the delegate issues still
# exists and systemd currently does not support the cgroup feature set required
# for containers run by docker
# 在 ExecStart后面添加 “-H tcp://0.0.0.0”
ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock -H tcp://0.0.0.0
ExecReload=/bin/kill -s HUP $MAINPID
TimeoutSec=0
RestartSec=2
Restart=always

然后重启 Docker Daemon 服务

systemctl daemon-reload
systemctl restart docker.service

通过以下命令访问远程 Docker Server

docker -H 服务器IP地址 info

3) Docker Container

上文已经对此进行了描述,不再赘述:

Docker 容器(Container)是一个运行时的概念,可以理解为一个简易的 Linux 系统环境(包括 root 用户权限、进程空间、网络空间等概念)以及运行在其中的应用程序。每个 Docker 容器本质上就是一个 Linux 进程,拥有自己的上下文环境,彼此隔离。Docker 引擎能够对一个容器进行启动、停止、删除等操作。

4) Docker Image

上文已经对此进行了描述,不再赘述:

Docker 镜像(Image)和虚拟机镜像的概念是一样的,可以将其理解为一个面向 Docker 引擎的只读模板,可用于批量创造可运行的容器实例。Docker 镜像可以看作是一个特殊的文件系统,除了提供容器运行时所需的程序、库、资源、配置等文件外,还包含了一些为运行时准备的一些配置参数(如环境变量、用户等)。镜像不包含任何动态数据,其内容在构建之后也不会被改变。镜像是创建 Docker 容器的基础,而 Docker 体系能够提供一套简单的机制创建和更新已有的镜像,也可以从网上下载一个制作好的现成的镜像。

5) Docker Registry

上文已经对此进行了描述,不再赘述:

Docker 仓库(Reopsitory)类似代码仓库,是 Docker 体系集中存放镜像文件的场所。一般情况下,一个仓库会包含同一个软件不同版本的镜像,用“标签”的概念来标记版本 。可以通过<仓库名>:<标签>的格式来精确定位具体采用哪个镜像。如果不指定标签,则采用 latest 作为默认标签。

根据存储的镜像公开与否,可以分为公开仓库(Public)和私有仓库(Private),目前最大的公开仓库是 Docker Hub,用户可以在自己的本地网络中创建私有仓库。

Docker 利用仓库管理镜像的理念类似于 Git,默认情况下 Docker 会在中央仓库(Docker Hub 和 Docker Cloud)寻找镜像文件。

运行 docker push、docker pull、docker search 命令时,实际上是 Docker Client 通过 Docker Daemon 与 Docker Registry 进行通信。

Docker Client-Daemon-Registry 的关系

关于 Docker 的架构详解,有必要会单独写一篇学习笔记,本篇笔记不再展开了。

四、Docker 容器的安装

Docker 官方文档是最好的安装指南:Install Docker on Ubuntu

以 Ubuntu 为例,可以采用两种方式进行安装:

  1. Docker Repository(推荐方式)
  2. Docker Debian Package
方式一:Docker Repository
  1. 更新 apt 列表
sudo apt-get install \
    apt-transport-https \
    ca-certificates \
    curl \
    gnupg-agent \
    software-properties-common
  1. 允许 apt 能够通过 HTTPs 方式使用仓库
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
  1. 添加 Dokcer 官方 GPG Key
sudo apt-key fingerprint 0EBFCD88
  1. 设置 Docker-CE 稳定版的仓库
sudo add-apt-repository \
     "deb [arch=amd64] https://download.docker.com/linux/ubuntu \
     $(lsb_release -cs) \
     stable"
  1. 安装最新版本的 Docker
sudo apt-get update
sudo apt-get install docker-ce docker-ce-cli containerd.io

如果想安装指定版本的 Docker 怎么办?

# 获取 Docker 版本列表
apt-cache madison docker-ce

# 安装指定版本,修改 "<>" 中的版本号
sudo apt-get install docker-ce=<18.03.1~ce-0~ubuntu>
  1. 检查 Docker 版本
sudo docker version

Client: Docker Engine - Community
 Version:           19.03.5
 API version:       1.40
 Go version:        go1.12.12
 Git commit:        633a0ea838
 Built:             Wed Nov 13 07:29:52 2019
 OS/Arch:           linux/amd64
 Experimental:      false

Server: Docker Engine - Community
 Engine:
  Version:          19.03.5
  API version:      1.40 (minimum version 1.12)
  Go version:       go1.12.12
  Git commit:       633a0ea838
  Built:            Wed Nov 13 07:28:22 2019
  OS/Arch:          linux/amd64
  Experimental:     false
 containerd:
  Version:          1.2.10
  GitCommit:        b34a5c8af56e510852c35414db4c1f4fa6172339
 runc:
  Version:          1.0.0-rc8+dev
  GitCommit:        3e425f80a8c931f88e6d94a8c831b9d5aa481657
 docker-init:
  Version:          0.18.0
  GitCommit:        fec3683
方式二:Docker Debian Package
  1. 下载 Docker 压缩包
    下载地址:Ubuntu Docerk 压缩包地址

  2. 安装 Docker

sudo dpkg -i /home/andy/docker/package.deb

五、Docker 容器的基本操作

首先,通过一个 HelloWord 的例子,对 Docker 体系各组件的协作流程有个整体的理解,这对进一步掌握和理解 Docker 的操作方法会有很好的帮助:

Docker Hello-World

从 hello-world 打印中,官方还给出了如何运行一个 Ubuntu 容器的例子,可以认为在这个容器中运行的是一个极简的 Ubuntu Linux 系统,一个极为轻量的 GuestOS。

Docker Ubuntu

Docker 的操作命令也是非常多的,执行 docker --help 能够看到所有命令接口。这篇笔记只记录一些关于镜像、容器、仓库的基本操作方法。

andy-zhang@localhost:~$ sudo docker --help
[sudo] password for andy-zhang: 

Usage:  docker [OPTIONS] COMMAND

A self-sufficient runtime for containers

Options:
      --config string      Location of client config files (default "/home/andy-zhang/.docker")
  -c, --context string     Name of the context to use to connect to the daemon (overrides DOCKER_HOST env var and default
                           context set with "docker context use")
  -D, --debug              Enable debug mode
  -H, --host list          Daemon socket(s) to connect to
  -l, --log-level string   Set the logging level ("debug"|"info"|"warn"|"error"|"fatal") (default "info")
      --tls                Use TLS; implied by --tlsverify
      --tlscacert string   Trust certs signed only by this CA (default "/home/andy-zhang/.docker/ca.pem")
      --tlscert string     Path to TLS certificate file (default "/home/andy-zhang/.docker/cert.pem")
      --tlskey string      Path to TLS key file (default "/home/andy-zhang/.docker/key.pem")
      --tlsverify          Use TLS and verify the remote
  -v, --version            Print version information and quit

Management Commands:
  builder     Manage builds
  config      Manage Docker configs
  container   Manage containers
  context     Manage contexts
  engine      Manage the docker engine
  image       Manage images
  network     Manage networks
  node        Manage Swarm nodes
  plugin      Manage plugins
  secret      Manage Docker secrets
  service     Manage services
  stack       Manage Docker stacks
  swarm       Manage Swarm
  system      Manage Docker
  trust       Manage trust on Docker images
  volume      Manage volumes

Commands:
  attach      Attach local standard input, output, and error streams to a running container
  build       Build an image from a Dockerfile
  commit      Create a new image from a container's changes
  cp          Copy files/folders between a container and the local filesystem
  create      Create a new container
  diff        Inspect changes to files or directories on a container's filesystem
  events      Get real time events from the server
  exec        Run a command in a running container
  export      Export a container's filesystem as a tar archive
  history     Show the history of an image
  images      List images
  import      Import the contents from a tarball to create a filesystem image
  info        Display system-wide information
  inspect     Return low-level information on Docker objects
  kill        Kill one or more running containers
  load        Load an image from a tar archive or STDIN
  login       Log in to a Docker registry
  logout      Log out from a Docker registry
  logs        Fetch the logs of a container
  pause       Pause all processes within one or more containers
  port        List port mappings or a specific mapping for the container
  ps          List containers
  pull        Pull an image or a repository from a registry
  push        Push an image or a repository to a registry
  rename      Rename a container
  restart     Restart one or more containers
  rm          Remove one or more containers
  rmi         Remove one or more images
  run         Run a command in a new container
  save        Save one or more images to a tar archive (streamed to STDOUT by default)
  search      Search the Docker Hub for images
  start       Start one or more stopped containers
  stats       Display a live stream of container(s) resource usage statistics
  stop        Stop one or more running containers
  tag         Create a tag TARGET_IMAGE that refers to SOURCE_IMAGE
  top         Display the running processes of a container
  unpause     Unpause all processes within one or more containers
  update      Update configuration of one or more containers
  version     Show the Docker version information
  wait        Block until one or more containers stop, then print their exit codes

Run 'docker COMMAND --help' for more information on a command.

镜像的基本操作:

1)获取镜像

【命令】:docker pull NAME[:TAG]
【说明】:使用该指令从网络上下载指定的镜像文件。如果不显示的指定 “TAG”,默认选择 “latest” 标签,即对应仓库中最新版本的镜像文件。

以获取 Ubuntu 镜像为例:

andy-zhang@localhost:~$ sudo docker pull ubuntu:latest
[sudo] password for andy-zhang: 
Unable to find image 'ubuntu:latest' locally
latest: Pulling from library/ubuntu
5c939e3a4d10: Pull complete 
c63719cdbe7a: Pull complete 
19a861ea6baf: Pull complete 
651c9d2d6c4f: Pull complete 
Digest: sha256:8d31dad0c58f552e890d68bbfb735588b6b820a46e459672d96e585871acc110
Status: Downloaded newer image for ubuntu:latest

Docker 仓库中最新的 Ubuntu 版本为 18.04.3。从下载过程中能看到一个小细节,镜像是分层的,“5c939e3a4d10” 这样的数字代表每一层的ID。分层其实是 AUFS(Advanced Union File System,联合文件系统) 的重要概念,可以实现 Docker 镜像的增量保存与更新。AUFS 是比较重要的机制,但这里不再展开了。

docker pull 指令默认从 Docker 官方的注册服务器(也可以称作镜像源)中进行下载,"docker pull ubuntu:latest" 这条指令等价于 “docker pull registry.hub.docker.com/ubuntu:latest”,也就是从默认的注册服务器“registry.hub.docker.com”中的 “ubuntu” 仓库中下载标签为 “latest” 的镜像文件。镜像源可以改变,比如从 DockerPool 社区的镜像源 “dl.dockerpol.com” 下载,但需要在命令中进行显示指定

镜像下载到本地后,就可以进行各种操作了,比如利用该镜像创建一个 Ubuntu 容器,并在其中运行bash应用:

andy-zhang@localhost:~$ sudo docker run -i -t ubuntu bash
root@f90e0ca4b855:/# pwd
/

root@f90e0ca4b855:/# whoami 
root

root@f90e0ca4b855:/# uname -a
Linux f90e0ca4b855 4.4.0-62-generic #83-Ubuntu SMP Wed Jan 18 14:10:15 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux

2)查看镜像

【命令】:docker images
【说明】:使用该指令查询本地已经拥有的镜像。

andy-zhang@localhost:~$ sudo docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
ubuntu              latest              ccc6e87d482b        2 weeks ago         64.2MB
hello-world         latest              fce289e99eb9        13 months ago       1.84kB

【命令】:docker inspect NAME[:TAG]
【说明】:获取镜像的详细信息,返回 JSON 格式的消息。使用者一般情况下应该不太需要查询如此详细的信息。

andy-zhang@localhost:~$ sudo docker inspect hello-world:latest
[
    {
        "Id": "sha256:fce289e99eb9bca977dae136fbe2a82b6b7d4c372474c9235adc1741675f587e",
        "RepoTags": [
            "hello-world:latest"
        ],
        "RepoDigests": [
            "hello-world@sha256:9572f7cdcee8591948c2963463447a53466950b3fc15a247fcad1917ca215a2f"
        ],
        "Parent": "",
        "Comment": "",
        "Created": "2019-01-01T01:29:27.650294696Z",
        "Container": "8e2caa5a514bb6d8b4f2a2553e9067498d261a0fd83a96aeaaf303943dff6ff9",
        "ContainerConfig": {
            "Hostname": "8e2caa5a514b",
            "Domainname": "",
            "User": "",
            "AttachStdin": false,
            "AttachStdout": false,
            "AttachStderr": false,
            "Tty": false,
            "OpenStdin": false,
            "StdinOnce": false,
            "Env": [
                "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
            ],
            "Cmd": [
                "/bin/sh",
                "-c",
                "#(nop) ",
                "CMD [\"/hello\"]"
            ],
            "ArgsEscaped": true,
            "Image": "sha256:a6d1aaad8ca65655449a26146699fe9d61240071f6992975be7e720f1cd42440",
            "Volumes": null,
            "WorkingDir": "",
            "Entrypoint": null,
            "OnBuild": null,
            "Labels": {}
        },
        "DockerVersion": "18.06.1-ce",
        "Author": "",
        "Config": {
            "Hostname": "",
            "Domainname": "",
            "User": "",
            "AttachStdin": false,
            "AttachStdout": false,
            "AttachStderr": false,
            "Tty": false,
            "OpenStdin": false,
            "StdinOnce": false,
            "Env": [
                "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
            ],
            "Cmd": [
                "/hello"
            ],
            "ArgsEscaped": true,
            "Image": "sha256:a6d1aaad8ca65655449a26146699fe9d61240071f6992975be7e720f1cd42440",
            "Volumes": null,
            "WorkingDir": "",
            "Entrypoint": null,
            "OnBuild": null,
            "Labels": null
        },
        "Architecture": "amd64",
        "Os": "linux",
        "Size": 1840,
        "VirtualSize": 1840,
        "GraphDriver": {
            "Data": {
              "MergedDir": "/var/lib/docker/overlay2/8fcf5abbb31dbe70e7fe9e6cc3d4515b9dfa243adee48efff812bcca9551d488/merged",
              "UpperDir": "/var/lib/docker/overlay2/8fcf5abbb31dbe70e7fe9e6cc3d4515b9dfa243adee48efff812bcca9551d488/diff",
              "WorkDir": "/var/lib/docker/overlay2/8fcf5abbb31dbe70e7fe9e6cc3d4515b9dfa243adee48efff812bcca9551d488/work"
            },
            "Name": "overlay2"
        },
        "RootFS": {
            "Type": "layers",
            "Layers": [
                "sha256:af0b15c8625bb1938f1d7b17081031f649fd14e6b233688eea3c5483994a66a3"
            ]
        },
        "Metadata": {
            "LastTagTime": "0001-01-01T00:00:00Z"
        }
    }
]

3)查找镜像

【命令】:docker search NAME
【说明】:搜索远端仓库中的镜像,默认为 Docker Hub 官方仓库。而且结果会按照星级进行自动排序。也可以直接访问 Docker Hub 的网址(Docker Hub),更直观一些。

andy-zhang@localhost:~$ sudo docker search php
NAME                            DESCRIPTION                                     STARS          OFFICIAL        AUTOMATED
php                             While designed for web development, the PHP …   5025           [OK]            
phpmyadmin/phpmyadmin           A web interface for MySQL and MariaDB.          937                            [OK]
adminer                         Database management in a single PHP file.       339            [OK]            
php-zendserver                  Zend Server - the integrated PHP application…   178            [OK]            
webdevops/php-nginx             Nginx with PHP-FPM                              149                            [OK]
webdevops/php-apache-dev        PHP with Apache for Development (eg. with xd…   115                            [OK]
webdevops/php-apache            Apache with PHP-FPM (based on webdevops/php)    96                             [OK]
bitnami/php-fpm                 Bitnami PHP-FPM Docker Image                    84                             [OK]
phpunit/phpunit                 PHPUnit is a programmer-oriented testing fra…   74                             [OK]
nazarpc/phpmyadmin              phpMyAdmin as Docker container, based on off…   60                             [OK]
circleci/php                    CircleCI images for PHP                         27                             
thecodingmachine/php            General-purpose ultra-configurable PHP images   26                             [OK]
adrianharabula/php7-with-oci8   Latest PHP 7.1 with apache and Oracle oci8      19                             [OK]
phpdockerio/php72-fpm           PHP 7.2 FPM base container for PHPDocker.io.    19                             [OK]
bitnami/phpmyadmin              Bitnami Docker Image for phpMyAdmin             16                             [OK]
phpdockerio/php7-fpm            PHP 7 FPM base container for PHPDocker.io.      14                             [OK]
graze/php-alpine                Smallish php7 alpine image with some common …   13                             [OK]
phpdockerio/php56-fpm           PHP 5.6 FPM base container for PHPDocker.io     11                             [OK]
appsvc/php                      Azure App Service php dockerfiles               10                             [OK]
phpdockerio/php71-fpm           PHP 7.1 FPM base container for PHPDocker.io.    7                              [OK]
phpdockerio/php72-cli           PHP 7.2 CLI base container for PHPDocker.io.    4                              [OK]
phpdockerio/php56-cli           PHP 5.6 CLI base container for PHPDocker.io …   1                              [OK]
phpdockerio/php71-cli           PHP 7.1 CLI base container for PHPDocker.io.    1                              [OK]
phpdockerio/php7-cli            PHP 7 CLI base container image for PHPDocker…   1                              [OK]
isotopab/php                    Docker PHP                                      0                              [OK]

4)删除镜像

【命令】:docker rmi NAME[:TAG]
【说明】:删除指定的镜像文件,该镜像所有的 AUFS 层都会被删除掉。需要注意的是,如果存在用该镜像创建的容器时,镜像文件是无法被删除的,虽然可以通过添加 “-f” 参数强制删除,但不推荐这样干,可能会因为依赖关系导致出现一些莫名其妙的问题。详情参见如下示例中的注释。

#查询本地的镜像
andy-zhang@localhost:~$ sudo docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
ubuntu              latest              ccc6e87d482b        2 weeks ago         64.2MB
hello-world         latest              fce289e99eb9        13 months ago       1.84kB

#删除hello-world镜像,但提示冲突,因为存在用该镜像创建的容器,删除失败
andy-zhang@localhost:~$ sudo docker rmi hello-world
Error response from daemon: conflict: unable to remove repository reference "hello-world" (must force) - 
container 3dfa00a4e8b7 is using its referenced image fce289e99eb9

#查询系统中存在的容器,果然发现了用hello-world镜像创建的容器
andy-zhang@localhost:~$ sudo docker ps -a
CONTAINER ID    IMAGE           COMMAND         CREATED         STATUS                 PORTS       NAMES
3dfa00a4e8b7    hello-world     "/hello"        49 minutes ago  Exited (0) 49 minutes ago          boring_brattain

#删除该容器
andy-zhang@localhost:~$ sudo docker rm 3df
3df

#再次查询,hello-world容器已经不存在了
andy-zhang@localhost:~$ sudo docker ps -a
CONTAINER ID    IMAGE           COMMAND         CREATED         STATUS                 PORTS       NAMES

#再次删除,删除成功,所有AUFS层都被删除掉
andy-zhang@localhost:~$ sudo docker rmi hello-world:latest
Untagged: hello-world:latest
Untagged: hello-world@sha256:9572f7cdcee8591948c2963463447a53466950b3fc15a247fcad1917ca215a2f
Deleted: sha256:fce289e99eb9bca977dae136fbe2a82b6b7d4c372474c9235adc1741675f587e
Deleted: sha256:af0b15c8625bb1938f1d7b17081031f649fd14e6b233688eea3c5483994a66a3

#再次查询本地的镜像,已经没有hello-world
andy-zhang@localhost:~$ sudo docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
ubuntu              latest              ccc6e87d482b        2 weeks ago         64.2MB

5)创建镜像

创建镜像有三种方式:

基于 Dockerfile 的方式非常重要,后面单独写篇笔记,这里主要写一些第一种方式,基于容器创建。

【命令】:docker commit BASED_CONTAINER NAME[:TAG]
【说明】:基于已有的容器创建一个新的镜像。

下面的例子表示基于正在运行的一个容器,对其进行修改后生成一个新的镜像。

#查看本地存在的镜像,只有一个ubuntu
andy-zhang@localhost:~$ sudo docker images
[sudo] password for andy-zhang: 
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
ubuntu              latest              ccc6e87d482b        2 weeks ago         64.2MB

#基于ubuntu镜像启动一个容器,ed6ad16ae768就是容器ID
andy-zhang@localhost:~$ sudo docker run -it ubuntu:latest bash
root@ed6ad16ae768:/# 

#创建了一个文件,这时候该相对原ubuntu镜像已经发生了改变
root@ed6ad16ae768:/# cd /home/
root@ed6ad16ae768:/home# touch hello-andy
root@ed6ad16ae768:/home# ll
total 8
drwxr-xr-x 1 root root 4096 Feb  3 07:36 ./
drwxr-xr-x 1 root root 4096 Feb  3 07:36 ../
-rw-r--r-- 1 root root    0 Feb  3 07:36 hello-andy

#退出系统,也就是退出容器
root@ed6ad16ae768:/home# exit
exit

#基于ed6ad16ae768容器创建,名字为hello-andy
andy-zhang@localhost:~$ sudo docker commit ed6ad16ae768 hello-andy
sha256:fb6f9a2b58f7b232c24cbdf4746dcfbcf93ed3b0991d81e53f6d6054311af493

#再次查看本地存在的镜像,多了hello-andy这个镜像,该镜像其实就是在ubuntu系统中多创建了一个文件
andy-zhang@localhost:~$ sudo docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
hello-andy          latest              fb6f9a2b58f7        12 seconds ago      64.2MB
ubuntu              latest              ccc6e87d482b        2 weeks ago         64.2MB

#基于hello-andy镜像启动一个容器,1f235281f026是该容器ID
andy-zhang@localhost:~$ sudo docker run -it hello-andy:latest bash
root@1f235281f026:/# cd /home/

#能够看到,该容器是已经包含刚刚创建的hello-andy文件
root@1f235281f026:/home# ll
total 8
drwxr-xr-x 1 root root 4096 Feb  3 07:36 ./
drwxr-xr-x 1 root root 4096 Feb  3 07:39 ../
-rw-r--r-- 1 root root    0 Feb  3 07:36 hello-andy

使用这种方法,可以逐步构筑一个可复用的新镜像,比如一个 LAMP(Linux+Apache+MySQL+PHP)。

6)导出镜像

【命令】:docker save -o FILE
【说明】:将本地的镜像导出到本地文件系统中,这样就可以向传送普通文件一样传送 Docker 镜像文件,而不必通过 “pull” 指令从镜像仓库中获取。

andy-zhang@localhost:~$ sudo docker save -o hello-world-andy.tar hello-world:latest
andy-zhang@localhost:~$ ll
total 65104
drwxr-xr-x 4 andy-zhang andy-zhang     4096 Feb  3 00:13 ./
drwxr-xr-x 3 root       root           4096 Jan 31 07:43 ../
-rw------- 1 andy-zhang andy-zhang     1887 Feb  2 02:19 .bash_history
-rw-r--r-- 1 andy-zhang andy-zhang      220 Jan 31 07:43 .bash_logout
-rw-r--r-- 1 andy-zhang andy-zhang     3771 Jan 31 07:43 .bashrc
drwx------ 2 andy-zhang andy-zhang     4096 Jan 31 15:19 .cache/
-rw------- 1 root       root          12800 Feb  3 00:13 hello-world-andy.tar
-rw-r--r-- 1 andy-zhang andy-zhang      655 Jan 31 07:43 .profile
drwxrwxr-x 2 andy-zhang andy-zhang     4096 Jan 31 19:46 software/

7)导入镜像

【命令】:docker load < FILE
【说明】:从本地文件系统导入 Docker 镜像文件到本地仓库,是导出的逆操作。

#基于存在的ubuntu容器创建一个新的镜像ubuntu-hello-andy,前文已经描述,不再赘述
andy-zhang@localhost:~$ sudo docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
ubuntu              latest              ccc6e87d482b        2 weeks ago         64.2MB
hello-world         latest              fce289e99eb9        13 months ago       1.84kB
 
andy-zhang@localhost:~$ sudo docker run -it ubuntu:latest bash
root@3e96a231dff7:/# touch /home/hello-andy 
root@3e96a231dff7:/# ls /home
hello-andy
root@3e96a231dff7:/# exit
exit

andy-zhang@localhost:~$ sudo docker commit 3e96a231dff7 ubuntu-hello-andy:latest
sha256:0cf13cb05975c7b83b56c4e52ba697f7007ba7d3751b43787bae74d8476d7efc

andy-zhang@localhost:~$ sudo docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
ubuntu-hello-andy   latest              0cf13cb05975        10 seconds ago      64.2MB
ubuntu              latest              ccc6e87d482b        2 weeks ago         64.2MB
hello-world         latest              fce289e99eb9        13 months ago       1.84kB

#将新的ubuntu-hello-world镜像导出到本地文件系统
andy-zhang@localhost:~$ sudo docker save -o ubuntu-hello-andy.tar ubuntu-hello-andy:latest
andy-zhang@localhost:~$ ll
total 65104
drwxr-xr-x 4 andy-zhang andy-zhang     4096 Feb  3 00:35 ./
drwxr-xr-x 3 root       root           4096 Jan 31 07:43 ../
-rw------- 1 root       root       66609152 Feb  3 00:35 ubuntu-hello-andy.tar

#为了查看导入效果,先删除本地镜像库中的ubuntu-hello-world镜像删除
andy-zhang@localhost:~$ 
andy-zhang@localhost:~$ sudo docker rmi ubuntu-hello-andy
Untagged: ubuntu-hello-andy:latest
Deleted: sha256:0cf13cb05975c7b83b56c4e52ba697f7007ba7d3751b43787bae74d8476d7efc
Deleted: sha256:9f9d42f5978c3879d67fb975eb028bfc23e1f880de02ab99929cdb742a400e2c

andy-zhang@localhost:~$ sudo docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
ubuntu              latest              ccc6e87d482b        2 weeks ago         64.2MB
hello-world         latest              fce289e99eb9        13 months ago       1.84kB

#从本地文件系统的ubuntu-hello-andy.tar导入到本地镜像库
andy-zhang@localhost:~$ sudo docker load < ubuntu-hello-andy.tar 
44e4e13a1f5b: Loading layer [==================================================>]  3.584kB/3.584kB
Loaded image: ubuntu-hello-andy:latest

#导入成功,运行成功
andy-zhang@localhost:~$ sudo docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
ubuntu-hello-andy   latest              0cf13cb05975        2 minutes ago       64.2MB
ubuntu              latest              ccc6e87d482b        2 weeks ago         64.2MB
hello-world         latest              fce289e99eb9        13 months ago       1.84kB

andy-zhang@localhost:~$ sudo docker run -it ubuntu-hello-andy bash
root@651596d03b09:/# ls /home/
hello-andy

8)上传镜像

【命令】:docker push NAME[:TAG]
【说明】:将本地镜像上传到 Docker Hub,前提是在 Docker Hub 上注册了用户。由于注册申请还没有通过 Docker Hub 的审批,这里就不举例了。

容器的基本操作:

1)创建&启动容器

Docker 容器非常的轻量,可以随时创建或删除。有两种方法新建一个容器d

方法一:
【命令】:docker create NAME[:TAG] + docker start
【说明】:执行 create 指令创建的容器不会自动运行,处于停止状态,需要执行 start 指令将其启动起来。

#查询系统中存在哪些容器
andy-zhang@localhost:~$ sudo docker ps -a
CONTAINER ID        IMAGE                COMMAND        CREATED          STATUS             PORTS    NAMES
3e96a231dff7        ubuntu:latest        "bash"         3 hours ago      Exited (127) 3 hours ago    angry_wu
81418356128d        hello-world:latest   "/hello"       3 hours ago      Exited (0) 2 minutes ago    stoic_merkle

#利用hello-world镜像创建一个新的容器
andy-zhang@localhost:~$ sudo docker images
REPOSITORY          TAG                 IMAGE ID        CREATED          SIZE
ubuntu              latest              ccc6e87d482b    2 weeks ago      64.2MB
hello-world         latest              fce289e99eb9    13 months ago    1.84kB

andy-zhang@localhost:~$ sudo docker create hello-world
a98bb9e79779affb3cb57df091d3a58ef5d9a0924562e8148e7d08fa3af6e639

#再次查询系统中存在哪些容器,系统中已经存在两个基于hello-world镜像创建的容器
andy-zhang@localhost:~$ sudo docker ps -a
CONTAINER ID        IMAGE                COMMAND        CREATED          STATUS             PORTS    NAMES
a98bb9e79779        hello-world          "/hello"       8 seconds ago    Created                     bold_mendel
3e96a231dff7        ubuntu:latest        "bash"         3 hours ago      Exited (127) 3 hours ago    angry_wu
81418356128d        hello-world:latest   "/hello"       3 hours ago      Exited (0) 3 minutes ago    stoic_merkle

#用start指令启动新创建的容器
andy-zhang@localhost:~$ sudo docker start -i a98bb9e79779

Hello from Docker!
This message shows that your installation appears to be working correctly.

To generate this message, Docker took the following steps:
 1. The Docker client contacted the Docker daemon.
 2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
    (amd64)
 3. The Docker daemon created a new container from that image which runs the
    executable that produces the output you are currently reading.
 4. The Docker daemon streamed that output to the Docker client, which sent it
    to your terminal.

To try something more ambitious, you can run an Ubuntu container with:
 $ docker run -it ubuntu bash

Share images, automate workflows, and more with a free Docker ID:
 https://hub.docker.com/

For more examples and ideas, visit:
 https://docs.docker.com/get-started/

方法二:
【命令】:docker run NAME[:TAG]
【说明】:执行 run 指令等价于 start+start,是更常用的一种方式。执行 run 指令后,Docker 后台引擎的动作是:

这里解释一下上面运行 Ubuntu 容器的时候,为何会跟着 “-i” 和 “-t” 两个参数。

#run指令不携带任何参数
andy-zhang@localhost:~$ sudo docker run ubuntu:latest
[sudo] password for andy-zhang: 

#run指令携带-i和-t参数
andy-zhang@localhost:~$ sudo docker run -i -t ubuntu:latest
root@3dd7d01955af:/# ps
   PID TTY          TIME CMD
     1 pts/0    00:00:00 bash
    10 pts/0    00:00:00 ps

-t 选项让 Docker 分配一个伪终端(pseudo-tty),并绑定到容器的标准输入上;-i 选项则让容器的标准输入保持打开状态。对于 Ubuntu 应用,默认会执行 bash。那么,如果希望能够进行持续性的交互,这两个参数就是必要的了。

另外,很多时候,需要让 Docker 容器以守护形式(Daemonized)运行(Web服务器是典型的守护形式程序),可以增加 -d 选项来实现。下面这个例子,以守护形式启动一个 Ubuntu 的容器,执行 shell 程序,通过 docker logs CONTAINER 指令查看容器后台输出信息。

andy-zhang@localhost:~$ sudo docker run -d ubuntu:latest /bin/sh -c "while true; do echo hello andy; sleep 1; done"

andy-zhang@localhost:~$ sudo docker ps -a
CONTAINER ID    IMAGE            COMMAND                  CREATED           STATUS             PORTS      NAMES
f00b81c23380    ubuntu:latest    "/bin/sh -c 'while t…"   47 seconds ago    Up 45 seconds                 angry_mclaren
3dd7d01955af    ubuntu:latest    "/bin/bash"              39 minutes ago    Exited (0) 4 minutes ago      elastic_brattain

andy-zhang@localhost:~$ sudo docker logs f00b81c23380
hello andy
hello andy
hello andy
hello andy
hello andy
hello andy

2)终止容器

【命令】:docker stop
【说明】:终止容器的运行有两种方式,一种方式是执行 “stop” 指令方式,首先向容器发送一个 SIGTERM 信号,等待一段时间后(默认10秒)再向容器发送一个 SIGKILL 信号彻底终止容器;另一种方式是自然终止,也就是容器中运行的程序执行完毕后自行退出,容器会紧跟着中止运行。

下面的示例是终止上面创建的 while 死循环的容器:

#容器正在运行
andy-zhang@localhost:~$ sudo docker ps -a
CONTAINER ID   IMAGE            COMMAND                  CREATED          STATUS             PORTS      NAMES
f00b81c23380   ubuntu:latest    "/bin/sh -c 'while t…"   10 minutes ago   Up 10 minutes                 angry_mclaren

#执行终止指令
andy-zhang@localhost:~$ sudo docker stop f00b81c23380
f00b81c23380

#容器终止,能够明显感受到SIGTERM和SIGKILL信号10s间隔
andy-zhang@localhost:~$ sudo docker ps -a
CONTAINER ID   IMAGE            COMMAND                  CREATED          STATUS             PORTS      NAMES
f00b81c23380   ubuntu:latest    "/bin/sh -c 'while t…"   11 minutes ago   Exited (137) 4 seconds ago    angry_mclaren

3)进入容器

【命令】:docker exec CONTAINER COMMAND
【说明】:采用守护形式启动容器后,容器进入后台运行,用户无法看到容器中发生了什么。有的时候,有必要进入容器进行一些操作,这时候可以利用 “exec” 指令,如下示例:

#以守护形式启动一个容器
andy-zhang@localhost:~$ sudo docker run -d ubuntu:latest /bin/sh -c "while true; do echo hello andy; sleep 1; done"
  
andy-zhang@localhost:~$ sudo docker ps -a
CONTAINER ID    IMAGE            COMMAND                  CREATED          STATUS     PORTS   NAMES
5390d39f4ee0    ubuntu:latest    "/bin/sh -c 'while t…"   53 seconds ago   Up 53 seconds      nostalgic_babbage

#使用exec指令进入正在运行的容器中,执行各种操作
andy-zhang@localhost:~$ sudo docker exec -i -t 5390d39f4ee0 bash
root@5390d39f4ee0:/# ps -a
   PID TTY          TIME CMD
   146 pts/0    00:00:00 ps
root@5390d39f4ee0:/# ps -ax
   PID TTY      STAT   TIME COMMAND
     1 ?        Ss     0:00 /bin/sh -c while true; do echo hello andy; sleep 1; done
   131 pts/0    Ss     0:00 bash
   152 ?        S      0:00 sleep 1
   153 pts/0    R+     0:00 ps -ax

4)删除容器

【命令】:docker rm CONTAINER
【说明】:删除处于终止状态的容器,如果容器运行中,需要先停止,否则会提示失败,可以使用 “-f” 选项强制进行删除。

#删除正在运行的容器,提示失败
andy-zhang@localhost:~$ sudo docker rm 5390d39f4ee0
Error response from daemon: You cannot remove a running container
5390d39f4ee0c41731ec784bb3ed9c41b62b04ac6cfd391e4690eb07e574d4e5. Stop the container before attempting removal or force remove

#强制删除
andy-zhang@localhost:~$ sudo docker rm -f 5390d39f4ee0
5390d39f4ee0

#删除成功
andy-zhang@localhost:~$ sudo docker ps -a
CONTAINER ID        IMAGE           COMMAND         CREATED         STATUS          PORTS           NAMES

别混淆:删除容器是 “rm” 指令,删除镜像是 “rmi” 指令。

仓库的基本操作:

仓库(Repository)是集中存放镜像的地方。但仓库容易和注册服务器(Registry)相混淆。准确的说,注册服务器是存放仓库的具体服务器,可以存储多个仓库;而每个仓库下面可以存放多个镜像,用标签(TAG)进行区分。通常情况下,一个仓库中存放的都是同一类型的镜像。

也就是说,精确定位具体的镜像文件的 “URL” 是:Image = Registry + Repository + Tag。

这三者的关系可以用下面的图来表示:

Registry-Repository-Tag

镜像资源一般可以分成两类,一类是官方提供的,由 Docker 公司创建、验证、发布;另一类是第三方组织/个人提供的。在前面镜像基本操作的笔记中,提到了 “search” 指令。从该指令的查询结果中能够看出来,由官方发布的镜像,往往用单个单词作为名字;而第三方组织或个人提供的,往往都带有用户名前缀。

如下面的示例所示,官方发布的镜像有 “php”、“adminer”、“php-zendserver”,第三方组织的则有 “phpmyadmin/phpmyadmin”、“webdevops/php-ngnix”等。

andy-zhang@localhost:~$ sudo docker search php
NAME                            DESCRIPTION                                     STARS     OFFICIAL    AUTOMATED
php                             While designed for web development, the PHP …   5025      [OK]        
phpmyadmin/phpmyadmin           A web interface for MySQL and MariaDB.          937                   [OK]
adminer                         Database management in a single PHP file.       339       [OK]        
php-zendserver                  Zend Server - the integrated PHP application…   178       [OK]        
webdevops/php-nginx             Nginx with PHP-FPM                              149                   [OK]
webdevops/php-apache-dev        PHP with Apache for Development (eg. with xd…   115                   [OK]
webdevops/php-apache            Apache with PHP-FPM (based on webdevops/php)    96                    [OK]
bitnami/php-fpm                 Bitnami PHP-FPM Docker Image            

在当前的工作中,主要适用官方提供的仓库就可以满足要求,对于如何创建和适用私有仓库,在这篇笔记中不再涉及,如果工作中有需要时,再进行研究了。


以上,就是 Docker 基本的概念与基本的操作方法。敲了很多字,但心情很爽。后面还会继续补充几篇笔记,涉及 Docker 的数据管理、基础网络配置、Dockerfile、经典应用、Docker 安全等内容。

永远学习。

也向一线抗战的医护人员致敬。

Docker
上一篇下一篇

猜你喜欢

热点阅读