【Docker学习笔记(一)】简介、核心概念、安装以及常用命令

【Docker 学习笔记目录】


【本文目录】


1 Docker 概述

1.1 Docker是什么

Docker 是一个虚拟环境容器,可以将你的开发环境、代码、配置文件等一并打包到这个容器中,并发布和应用到任意平台中

比如,你在本地用 Python 开发网站后台,开发测试完成后,就可以将 Python3 及其依赖包、Django 及其各种插件、Mysql、Nginx 等打包到一个容器中,然后部署到任意你想部署到的环境。换种说法,也就是软件带环境安装

Docker 的主要目标是 “Build,Ship,and Run Any App,Anywhere” ,也就是通过对应用组件的封装、分发、部署、运行等生命周期的管理,使用户的 APP 及其运行环境能够做到 “一次封装,到处运行”

Linux 容器管理的出现就解决了这样一个问题,而 Docker 就是在它的基础上发展过来的。将应用运行在 Docker 容器上,而 Docker 容器在任何操作系统都是一致的,这就实现了跨平台、跨服务器。只需要一次配置好环境,换到别的机器上就可以一键部署,大大简化了操作

1.2 Docker 能干什么

面向开发人员的 Docker

开发人员使用了 Docker,就不必安装和配置复杂的数据库,也无需在不兼容语言工具链版本之间切换时担心。应用容器化之后,其复杂性就被转移到能够轻松构建、共享和运行的容器中。当有新同事安排到新的代码库时,无需再费时费力地安装软件和解释设置过程。以 Dockerfile 文件形式发布的代码使用起来非常简单:首先安装 Docker 和编辑器,然后拉取作为 Docker 镜像打包在一起的依赖资源,短短数分钟,就能够构建和调试应用了

面向系统管理员的 Docker

Docker 简化了软件交付。既能顺利地开发和部署漏洞补丁与新功能,还能够实时扩展应用。Docker 是开发人员和 IT 运维团队的秘密武器。有了 Docker,他们能够自动并安全地构建、交付、测试和部署应用,顺利地进行移植。无需再阅读令人烦恼的 Wiki、自述文件、运行手册、便利贴等等陈旧冗余的信息

面向企业的 Docker

Docker 是现代应用平台的核心,是开发人员与 IT 运维、Linux 和 Windows 之间的纽带。Docker 既适用于云,也可以在本地部署;既支持传统架构,也支持微服务架构。使用 Docker 可以构建、连接、保护和调度容器,从开发到生产全程进行管理。Docker 以最优成本确保应用敏捷、支持云且安全,伴随企业踏上数字转型的征程

1.3 容器 VS 虚拟机

容器 是一个应用层抽象,用于将代码和依赖资源打包在一起。多个容器可以在同一台机器上运行,共享操作系统内核,但各自作为独立的进程在用户空间中运行。与虚拟机相比,容器占用的空间较少(容器镜像大小通常只有几十兆),瞬间就能完成启动

虚拟机(VM) 是一个物理硬件层抽象,用于将一台服务器变成多台服务器。管理程序允许多个 VM 在一台机器上运行。每个 VM 都包含一整套操作系统、一个或多个应用、必要的二进制文件和库资源,因此占用大量空间。而且 VM 启动也十分缓慢

容器和虚拟机具有相似的资源隔离和分配优势,但功能有所不同,因为容器虚拟化的是操作系统,而不是硬件,因此容器更容易移植,效率也更高

容器和虚拟机共用

将容器和虚拟机配合使用,为应用的部署和管理提供极大的灵活性


2 Docker 核心概念

镜像(Image):类似于虚拟机中的镜像,是一个包含有文件系统的面向 Docker 引擎的只读模板。任何应用程序运行都需要环境,而镜像就是用来提供这种运行环境的。例如一个 Ubuntu 镜像就是一个包含 Ubuntu 操作系统环境的模板,同理在该镜像上装上 Apache 软件,就可以称为 Apache 镜像

容器(Container):类似于一个轻量级的沙盒,可以将其看作一个极简的 Linux 系统环境(包括 root 权限、进程空间、用户空间和网络空间等),以及运行在其中的应用程序。Docker 引擎利用容器来运行、隔离各个应用。容器是镜像创建的应用实例,可以创建、启动、停止、删除容器,各个容器之间是是相互隔离的,互不影响。注意:镜像本身是只读的,容器从镜像启动时,Docker 在镜像的上层创建一个可写层,镜像本身不变,一个镜像可以创建多个容器

仓库(Repository):类似于代码仓库,这里是镜像仓库,是 Docker 用来集中存放镜像文件的地方。注意与注册服务器(Registry)的区别:注册服务器是存放仓库的地方,一般会有多个仓库;而仓库是存放镜像的地方,一般每个仓库存放一类镜像,每个镜像利用 tag 进行区分,比如 Ubuntu 仓库存放有多个版本(12.04、14.04等)的 Ubuntu 镜像

PS:容器和镜像的关系类似于面向对象编程的对象与类

Docker 使用 C/S 架构,Client 通过接口与 Server 进程通信实现容器的构建,运行和发布。Client 和 Server 可以运行在同一台集群,也可以通过跨主机实现远程通信

Build, Ship, and Run

  • Build(构建镜像):镜像就像是集装箱,包括文件以及运行环境等资源
  • Ship(运输镜像):主机和仓库间运输,这里的仓库就像是超级码头一样
  • Run (运行镜像):运行的镜像就是一个容器,容器就是运行程序的地方

3 Docker 安装

安装 Docker

参考:Centos7上安装docker - 风止雨歇 - 博客园

1、Docker 要求 CentOS 系统的内核版本高于 3.10 ,查看本页面的前提条件来验证你的CentOS 版本是否支持 Docker

  • $ uname -r

2、使用 root 权限登录 Centos。确保 yum 包更新到最新

  • $ sudo yum update

3、卸载旧版本(如果安装过旧版本的话)

  • $ sudo yum remove docker docker-common docker-selinux docker-engine

4、安装需要的软件包, yum-util 提供yum-config-manager功能,另外两个是devicemapper驱动依赖的

  • $ sudo yum install -y yum-utils device-mapper-persistent-data lvm2

5、设置yum源

  • sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo

6、可以查看所有仓库中所有docker版本,并选择特定版本安装

  • $ yum list docker-ce --showduplicates | sort -r

7、安装docker

  • $ sudo yum install docker-ce #repo中默认只开启stable仓库,故这里安装的是最新稳定版
  • $ sudo yum install <FQPN> # 例如:sudo yum install docker-ce-17.12.0.ce

8、启动并加入开机启动

  • $ sudo systemctl start docker
  • $ sudo systemctl enable docker

9、验证安装是否成功(有client和service两部分表示docker安装启动都成功了)

  • $ docker version

安装好之后,为了解决国内下载国外镜像很慢,我们使用国内阿里云的镜像加速器

首先进入到 阿里云控制台-容器镜像服务-镜像加速器,然后复制个人专属的加速器地址

然后按照文档进行操作(可以直接复制所有命令执行)

测试运行 hello world

在 centos7 中执行命令:docker run hello-world,安装成功如下所示

[root@localhost haha]# docker run hello-world
Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
9db2ca6ccae0: Pull complete 
Digest: sha256:4b8ff392a12ed9ea17784bd3c9a8b1fa3299cac44aca35a85c90c5e3c7afacdc
Status: Downloaded newer image for hello-world:latest

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/engine/userguide/

那么这个 run 都做了什么呢?


4 常用命令

4.1 镜像命令

1、查看所有顶层(top-level)镜像的列表

  • docker image [OPTIONS]
    • -a :列出本地所有的镜像(含中间镜像层)
    • -q :只列出镜像 ID
    • --digests :显示镜像的摘要信息
    • --no-trunc :显示完整的镜像信息
[root@localhost haha]# docker images -a
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
tomcat              latest              2d43521f2b1a        10 days ago         463MB
centos              latest              49f7960eb7e4        7 weeks ago         200MB
  • REPOSITORY :镜像的仓库源
  • TAG :镜像的标签
  • IMAGE ID :镜像的 ID 号(唯一)
  • CREATED :镜像的创建时间
  • SIZE :镜像的大小

实际上,在这里我们没有办法区分一个镜像和一个只读层,所以我们提出了 top-level 镜像。只有创建容器时使用的镜像或者是直接 pull 下来的镜像能被称为顶层(top-level)镜像,并且每一个顶层镜像下面都隐藏了多个镜像层

2、从 Docker Hub 查找镜像

  • docker search [OPTIONS] <镜像名>
    • --automated :只列出 automated build 类型的镜像
    • --no-trunc :显示完整的镜像描述
    • -s :列出收藏数(STARS)不小于指定值的镜像
[root@localhost haha]# docker search -s 30 tomcat
Flag --stars has been deprecated, use --filter=stars=3 instead
NAME                DESCRIPTION                                     STARS               OFFICIAL            AUTOMATED
tomcat              Apache Tomcat is an open source implementati…   1950                [OK]                
tomee               Apache TomEE is an all-Apache Java EE certif…   53                  [OK]                
dordoka/tomcat      Ubuntu 14.04, Oracle JDK 8 and Tomcat 8 base…   49                                      [OK]

3、从镜像仓库中拉取或者更新指定镜像

  • docker pull [OPTIONS] <镜像名>[:TAG]
    • -a :拉取所有 tagged 镜像
    • --disable-content-trust :忽略镜像的校验,默认开启
[root@localhost haha]# docker pull nginx
Using default tag: latest
latest: Pulling from library/nginx
be8881be8156: Pull complete 
32d9726baeef: Pull complete 
87e5e6f71297: Pull complete 
Digest: sha256:d85914d547a6c92faa39ce7058bd7529baacab7e0cd4255442b04577c4d1f424
Status: Downloaded newer image for nginx:latest

4、删除本地一个或多少镜像

  • docker rmi [OPTIONS] <镜像名1|镜像 ID 1> [<镜像名2|镜像 ID 2> ...]
    • -f :强制删除
    • --no-prune :不移除该镜像的过程镜像,默认移除
[root@localhost haha]# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
tomcat              latest              2d43521f2b1a        10 days ago         463MB
hello-world         latest              2cb0d9787c4d        2 weeks ago         1.85kB
[root@localhost haha]# docker rmi 2cb0d9787c4d
Error response from daemon: conflict: unable to delete 2cb0d9787c4d (must be forced) - image is being used by stopped container 14a305479dd2
[root@localhost haha]# docker rmi -f 2cb0d9787c4d
Untagged: hello-world:latest
Untagged: hello-world@sha256:4b8ff392a12ed9ea17784bd3c9a8b1fa3299cac44aca35a85c90c5e3c7afacdc
Deleted: sha256:2cb0d9787c4dd17ef9eb03e512923bc4db10add190d3f84af63b744e353a9b34
[root@localhost haha]# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
tomcat              latest              2d43521f2b1a        10 days ago         463MB

还可以使用 docker rmi -f ${docker images -qa} 删除全部镜像

5、将本地的镜像上传到镜像仓库,要先登陆到镜像仓库)

  • docker push [OPTIONS] <镜像名>[:TAG]
    • --disable-content-trust:忽略镜像的校验,默认开启

4.2 容器命令(上)

1、新建并启动容器:

  • docker run [OPTIONS] <镜像名> [COMMAND] [ARG...]
    • --name="容器新名字" :为容器指定一个名称
    • -d :后台运行容器,并返回容器ID,即启动守护式容器
    • -i :以交互模式运行容器,通常与 -t 同时使用
    • -t :为容器重新分配一个伪输入终端,通常与 -i 同时使用
    • -P :随机端口映射
    • -p :端口映射,格式有四种
      • ip:hostPort:containerPort
      • ip::containerPort
      • hostPort:containerPort
      • containerPort
    • -h "hostname" :指定容器的 hostname
    • -e username="value" :设置环境变量
    • --env-file=[] :从指定文件读入环境变量
[root@localhost lycai]# docker run -it centos
[root@70e60970099a /]# ls
bin  etc   lib    media  opt   root  sbin  sys  usr
dev  home  lib64  mnt    proc  run   srv   tmp  var
[root@70e60970099a /]# 

2、列出容器

  • docker ps [OPTIONS]
    • -a :显示所有的容器,包括未运行的
    • -l :显示最近创建的容器
    • -n :列出最近创建的n个容器
    • -q :静默模式,只显示容器编号
    • -f :根据条件过滤显示的内容
    • -s :显示总的文件大小
    • --format :指定返回值的模板文件
    • --no-trunc :不截断输出
[root@localhost lycai]# docker ps -n 5
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS                        PORTS               NAMES
70e60970099a        centos              "/bin/bash"         2 minutes ago       Exited (127) 44 seconds ago                       dreamy_einstein
994c3552ee20        centos              "/bin/bash"         2 hours ago         Up 2 hours                                        goofy_shtern
88a46ee5b51b        centos              "/bin/bash"         2 hours ago         Up 2 hours                                        stupefied_thompson
9505ae1b2ee7        centos              "/bin/bash"         2 hours ago         Up 2 hours                                        relaxed_blackwell
15c0168ef750        centos              "/bin/bash"         2 hours ago         Up 2 hours                                        flamboyant_meninsky

3、退出容器

  • exit / ctrl + p + q
    • exit :容器停止退出
    • ctrl + p + q :容器不停止退出

4、启动一个或多个已经被停止的容器

  • docker start [OPTIONS] <容器名1|容器 ID1> [<容器名2|容器 ID2>...]

5、停止一个运行中的容器

  • docker stop [OPTIONS] <容器名|容器 ID>

6、重启容器

  • docker restart [OPTIONS] <容器名|容器 ID>

7、杀掉一个运行中的容器

  • docker kill [OPTIONS] <容器名|容器 ID>
    • -s :向容器发送一个信号

8、删除一个或多少容器

  • docker rm [OPTIONS] <容器名1|容器 ID1> [<容器名2|容器 ID2>...]
    • -f :通过 SIGKILL 信号强制删除一个运行中的容器
    • -l :移除容器间的网络连接,而非容器本身
    • -v :删除与容器关联的卷

还可以通过 docker rm -f ${docker ps -a -q} 或者 docker ps -a -q | xargs docker rm 一次性删除多个容器

9、提交容器副本使之称为一个新的镜像:

  • docker commit [OPTIONS] <容器名 | 容器 ID> [<目标镜像名>[:TAG]]
    • -a :提交的镜像作者
    • -c :使用 Dockerfile 指令来创建镜像
    • -m :提交时的说明文字
    • -p :在 commit 时,将容器暂停

4.2 容器命令(下)

1、启动守护式容器

  • docker run -d <容器名|容器 ID>

使用镜像 centos 以后台模式启动一个容器之后,用 docker ps -a 进行查看,会发现容器已经退出。因为 Docker 容器想要后台运行,就必须有一个前台进程在容器中

2、获取容器的日志

  • docker logs [OPTIONS] <容器名|容器 ID>
    • -f :跟踪日志输出
    • -t :显示时间戳
    • --since :显示某个开始时间的所有日志
    • --tail :仅列出最新N条容器日志

3、查看容器中运行的进程信息,支持 ps 命令参数

  • docker top [OPTIONS] <容器名|容器 ID> [ps OPTIONS]

4、获取容器 / 镜像的元数据

  • docker inspect [OPTIONS] <容器名1|容器 ID1> [<容器名2|容器 ID2>...]
    • -f :指定返回值的模板文件
    • -s :显示总的文件大小
    • -type :为指定类型返回 JSON

5、在运行的容器中执行命令

  • docker exec [OPTIONS] <容器名|容器 ID> COMMAND [ARG...]
    • -d :分离模式,在后台运行
    • -i :以交互模式运行容器
    • -t :分配一个伪终端

6、连接到正在运行中的容器

  • docker attach [OPTIONS] <容器名|容器 ID>

要attach上去的容器必须正在运行,可以同时连接上同一个容器来共享屏幕

  • 官方文档中: attach 后可以通过 CTRL-C 来 detach
    • 如果容器当前在运行 bash,CTRL-C 自然是当前行的输入,没有退出
    • 如果容器当前正在前台运行进程,如输出 nginx 的 access.log 日志,CTRL-C不仅会导致退出容器,而且还stop了
  • 这不是我们想要的,detach的意思按理应该是脱离容器终端,但容器依然运行。好在 attach 是可以带上 --sig-proxy=false 来确保 CTRL-D 或 CTRL-C 不会关闭容器

exec 和 attach 的区别

  • exec:在容器中打开新的终端,并且可以启动新的进程
  • attach:直接进入容器启动命令的终端,不会启动新的进程

7、容器与主机之间的数据拷贝

容器 --> 主机

  • docker cp [OPTIONS] <容器名|容器 ID>:<容器数据路径> <主机目标路径>

主机 --> 容器

  • docker cp [OPTIONS] <主机数据路径> <容器名|容器 ID>:<容器目标路径>

PS:帮助命令:docker version / docker info / docker --help