zoukankan      html  css  js  c++  java
  • Docker (一) Docker入门

    Docker概述

    什么是Docker

    Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的 Linux 机器上,也可以实现虚拟化。容器是完全使用沙盒机制,相互之间不会有任何接口(类似 iPhone 的 app)。几乎没有性能开销,可以很容易地在机器和数据中心中运行。最重要的是,他们不依赖于任何语言、框架或包装系统。
     
    Docker使用Google公司推出的Go语言进行开发实现,基于Linux内核的cgroup,namespace,以及AUFS类的Union FS等技术,对进程进行封装隔离,属于操作系统层面的虚拟化技术。由于隔离的进程独立于宿主和其它的隔离的进程,因此也称其为容器

    Docker的基本概念

    Docker 容器是资源分割和调度的基本单位,封装整个服务的运行时环境,用于构建、发布和运行发布式应用的一个框架。它是一个跨平台,可移植并且简单易用的容器解决方案。

    Docker 容器可以快速自动化地部署应用,并通过操作系统内核技术(namespaces、cgroups等)为容器提供资源隔离与安全保障。Docker 作为轻量级的虚拟化方式,实现了PaaS平台高效部署、运行和维护。

    Docker 在容器的基础上,进行了进一步的封装,从文件系统、网络互联到进程隔离等待,极大的简化了容器的创建和维护。使得Docker技术比虚拟机技术更为轻便,快捷。

    Docker的优缺点

    Docker的有缺点往往会将它与传统的虚拟化技术进行对比,比如常见的虚拟机。如下是虚拟机和docker的结构图。

     

    优点:

    1. 高效的利用系统资源

    由于容器不需要进行硬件虚拟化以及运行完整的操作系统就可以启动一个应用,所以说Docker对系统资源的利用率比较高。相比起虚拟机技术,同一台物理机可以启动的应用Docker的数量是远远大于虚拟机的数量的。

    2. 更快速的启动时间

    传统的虚拟机需要启动一个完整的操作系统,启动起来往往需要几分钟,而Docker容器应用,由于直接运行于宿主机上,不需要启动一个完整的操作系统,所以基本上可以做到秒级的启动。大大的缩短了我们的开发,测试和部署的时间。

    3. 一致的运行环境
    开发过程中我们经常遇到环境一致性的问题,意思就是开发环境,测试环境和线上环境不一致,导致有些Bug并未在开发过程中没有被发现。而Docker的镜像提供了除内核外完整的运行时环境,确保了应用运行一致性,从而不会再出现再开发环境可以正常而生产环境不正常的问题。

    4. 持续的交付和部署

    对于开发和运维(DevOps)人员来说,最希望的是一次创建和配置,然后可以在任何环境中正常运行,无需担心环境问题。而使用Docker可以通过定制应用镜像来实现持续集成,持续交付,部署。开发人员可以通过Dockerfile来创建镜像,并结合持续集成,系统持续进行集成测试,而于运维人员则可以直接在生产环境中快速部署该镜像,甚至结合持续部署系统进行自动化部署。而使用Dockerfile使镜像透明化,不仅仅开发团队可以理解应用运行环境,也方便运维团队理解应用运行所需条件,帮助更好的生产环境中部署该镜像。

    5. 更轻松的迁移

    由于Docker确保了执行环境的一致性,使得应用的迁移更加容易,Docker可以在很多平台上运行,无论是物理机,还是虚拟机,公有云等其运行效果都是一致的。因此用户可以很容易将一个平台的运用迁移到其他平台上,而不用担心运行环境的变化导致无法正常运行的情况。

    6. 更轻松的维护和扩展

    Docker使用的分层存储以及镜像的技术,使得应用重复部分的复用更为容易,也使得应用的维护更新更加简单,基于基础镜像进一步扩展镜像也变得比较容易。此外Docker的众多的官方镜像就行Python的包一样给我们提供了非常多的镜像模板,大大的降低了应用服务的镜像制作成本。

    总的来说Docker和传统的虚拟机有以下差别:

    特性 容器 虚拟机
    启动 秒级 分钟级
    磁盘使用 一般为MB 一般为GB
    性能 接近原生 弱于
    系统支持量 单机支持上千个容器 一般几十个

    Docker的体系结构

     

     Docker是一个C/S架构,即Docker客户端是远程控制器,可以通过TCP REST向Docker Host发送请求,包括创建容器,运行容器,保存容器,删除容器等操作。Docker的服务端的Daemon对客户端的请求进行相应的管理。随后通过driver转发至容器中的libcontainer执行环境。libcontainer提供不同于linux内核隔离的接口,类似命名空间及控制组。这种架构允许许多个容器在共享同一个Linux内核的情况下完全隔离的运行。

    上述组成部分说明:

    Docker 镜像(Images) Docker 镜像是用于创建 Docker 容器的模板。
    Docker 容器(Container) 容器是独立运行的一个或一组应用。
    Docker 客户端(Client) Docker 客户端通过命令行或其他工具使用 Docker API (https://docs.docker.com/reference/api/docker_remote_api)与Docker 的守护进程通信。
    Docker 主机(Host) 一个物理或者虚拟的机器用来执行 Docker 守护进程和容器。
    Docker 仓库(Registry) Docker 仓库用来保存镜像,可以理解为代码控制中的代码仓库。Docker Hub(https://hub.docker.com)提供了庞大的镜像集合供使用。
    Docker Machine Docker Machine 是一个简化Docker安装的命令行工具,通过一个简单的命令即可在响应的平台上安装Docker,比如VirtualBox、Digital Ocean、Microsoft Azure。

    Docker的应用场景


     1. 简化配置

    这是Docker公司宣传的 Docker 的主要使用场景。
    Docker 能将运行环境和配置放在代码中然后部署,
    同一个 Docker 的配置可以在不同的环境中使用,
    这样就降低了硬件要求和应用环境之间耦合度。

     2. 代码流水线管理

    代码从开发者的机器到最终生产环境上的部署,需要经过很多的中间环境。
    而每一个中间环境都有微小的差别,Docker 给应用提供了一个从开发到上线均一致的环境,
    让代码的流水线变得简单不少。

     3. 提高开发效率

    Docker 能提升开发者的开发效率。不同的开发环境中,Docker 都可以把两件事做好,
    一是可以在开发环境、生产环境之间直接迁移,
    二是可以让我们快速搭建开发环境。
    开发环境的机器通常内存比较小,之前使用虚拟机的时候,我们经常要为开发环境的机器加内存,而使用Docker可以轻易的让几十个服务器在Docker中跑起来

     4. 隔离应用

    有很多原因会让我们选择在一个机器上运行不同的应用,Docker 非常适合在较低的成本下实现多种应用的隔离。

     5. 整合服务器

    Docker 隔离应用的能力使得Docker可以整合多个服务器以降低成本。由于没有操作系统的内存占用,以及能在多个实例之间共享没有使用的内存,
    Docker 可以比虚拟机提供更好的服务器整合解决方案。
    通常数据中心的服务器资源利用率只有30%,通过使用Docker 并进行有效的资源分配可以大幅度提高服务器资源的利用率。

     6. 调试能力

    Docker 提供了很多的工具,包括可以为容器设置检查点、设置版本和查看两个容器之间的差别,这些特性可以帮助调试Bug。

     7. 多租户环境

    另外一个Docker 的使用场景是在多租户的应用中,它可以避免关键应用的重写。
    我们一个特别的关于这个场景的例子是为物联网的应用开发一个快速、易用的多租户环境。
    这种多租户的基本代码非常复杂,很难处理,重新规划这样一个应用不但消耗时间,也浪费金钱。 使用Docker,可以为每一个租户的应用层的多个实例创建隔离的环境,这不仅简单而且成本低廉,当然这一切得益于Docker环境的启动速度和高效的diff命令。

     8. 快速部署

    在虚拟机之前,购入部署新的硬件资源需要消耗几天的时间。虚拟化技术(Virtualization)将这个时间缩短到了分钟级别。
    而Docker 通过为进程仅仅创建一个容器而无需启动一个操作系统,再次将这个过程缩短到了秒级。这正式Google和Facebook
    都看重的特性。我们可以创建销毁Docker 容器而无需担心重新启动带来的开销。

    Docker的核心概念

    Docker镜像

    Docker镜像类似于虚拟机的镜像,可以将它理解为一个只读的模板。例如:一个镜像可以包含一个基本的操作系统,里面仅仅安装了Nginx应用程序,我们就可以把这个镜像称之为Nginx镜像。

    镜像是创建容器的基础,通过版本管理和增量文件系统,Docker提供一套十分简单的机制创建,管理和更新现有镜像。用户也可以直接从网上下载镜像然后直接使用。

    Docker容器

    Docker容器类似一个轻量级的沙箱,Docker利用容器运行和隔离应用。容器是镜像运行起来后的一个实例。可以将容器比喻成面向对象的实例,而镜像就是面向对象中的类。容器与容器之间彼此是相互隔离,互不可见的。

    Docker镜像仓库

    Docker镜像仓库是用来集中存放镜像文件的地方。有公有的也有私有的。

    Docker安装部署

    系统准备:

    Docker 对CentOS的版本:
    CentOS 764-bit)
    CentOS 6.564-bit)或者更高的版本
    前提条件:
    Docker 运行在CentOS 7 上,要求系统为64位、系统内核为3.10以上
    Docker 运行在CentOS-6.5 或更高的版本的 CentOS 上,要求系统为64位、系统内核版本为2.6.32-431 或者更高版本。
    [root@hd3 ~]# cat /etc/redhat-release   #查看系统版本
    CentOS Linux release 7.5.1804 (Core) 
    [root@hd3 ~]# uname -a   #查看内核版本
    Linux hd3 3.10.0-862.el7.x86_64 #1 SMP Fri Apr 20 16:44:24 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux

    Docker安装

    我们可以直接去阿里云上找到快速的安装方法:安装连接

    # step 1: 安装必要的一些系统工具
    sudo yum install -y yum-utils device-mapper-persistent-data lvm2
    # Step 2: 添加软件源信息
    sudo yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
    # Step 3: 更新并安装Docker-CE
    sudo yum makecache fast
    sudo yum -y install docker-ce
    # Step 4: 开启Docker服务
    sudo systemctl start docker
    
    # 注意:
    # 官方软件源默认启用了最新的软件,您可以通过编辑软件源的方式获取各个版本的软件包。例如官方并没有将测试版本的软件源置为可用,您可以通过以下方式开启。同理可以开启各种测试版本等。
    # vim /etc/yum.repos.d/docker-ee.repo
    #   将[docker-ce-test]下方的enabled=0修改为enabled=1
    #
    # 安装指定版本的Docker-CE:
    # Step 1: 查找Docker-CE的版本:
    # yum list docker-ce.x86_64 --showduplicates | sort -r
    #   Loading mirror speeds from cached hostfile
    #   Loaded plugins: branch, fastestmirror, langpacks
    #   docker-ce.x86_64            17.03.1.ce-1.el7.centos            docker-ce-stable
    #   docker-ce.x86_64            17.03.1.ce-1.el7.centos            @docker-ce-stable
    #   docker-ce.x86_64            17.03.0.ce-1.el7.centos            docker-ce-stable
    #   Available Packages
    # Step2: 安装指定版本的Docker-CE: (VERSION例如上面的17.03.0.ce.1-1.el7.centos)
    # sudo yum -y install docker-ce-[VERSION]

    Docker镜像加速配置

    我们在下载网上镜像的时候速度会很慢,所以我们需要配置一个加速节点,同样的我们可以使用阿里云的加速节点,配置方式如下:配置连接

    sudo mkdir -p /etc/docker
    sudo tee /etc/docker/daemon.json <<-'EOF'
    {
      "registry-mirrors": ["https://tf2ihu8j.mirror.aliyuncs.com"]
    }
    EOF
    sudo systemctl daemon-reload
    sudo systemctl restart docker

    至此docker就安装完成,docker的镜像加速也完成。可以检查一下:

    [root@hd3 ~]# docker version
    Client: Docker Engine - Community
     Version:           19.03.12  #客户端版本
     API version:       1.40
     Go version:        go1.13.10
     Git commit:        48a66213fe
     Built:             Mon Jun 22 15:46:54 2020
     OS/Arch:           linux/amd64
     Experimental:      false
    
    Server: Docker Engine - Community
     Engine:
      Version:          19.03.12  # 服务端版本
      API version:      1.40 (minimum version 1.12)
      Go version:       go1.13.10
      Git commit:       48a66213fe
      Built:            Mon Jun 22 15:45:28 2020
      OS/Arch:          linux/amd64
      Experimental:     false
     containerd:
      Version:          1.2.13
      GitCommit:        7ad184331fa3e55e52b890ea95e65ba581ae3429
     runc:
      Version:          1.0.0-rc10
      GitCommit:        dc9208a3303feef5b3839f4323d9beb36df0a9dd
     docker-init:
      Version:          0.18.0
      GitCommit:        fec3683

    Docker基本使用

    Docker的基本命令

    [root@hd3 ~]# docker --help
    
    Usage:    docker [OPTIONS] COMMAND
    
    A self-sufficient runtime for containers
    
    Options:
          --config string      Location of client config files (default "/root/.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 "/root/.docker/ca.pem") --tlscert string Path to TLS certificate file (default "/root/.docker/cert.pem") --tlskey string Path to TLS key file (default "/root/.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 # 从当前shell中进入一个运行的容器 build Build an image from a Dockerfile # 通过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 #查看docker容器的变化 events Get real time events from the server # 从docker容器中获取实时事件 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 # kill指定的容器 load Load an image from a tar archive or STDIN # 从一个tar包中加载一个镜像 login Log in to a Docker registry # 注册或登陆一个docker源服务 logout Log out from a Docker registry # 从当前registory中退出 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 # 从docker镜像源服务器拉取指定镜像或库镜像 push Push an image or a repository to a registry # 推送指定镜像或者库镜像至docker源服务器 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) # 保存一个镜像为一个tar包 search Search the Docker Hub for images # 从docker hub中查找某个镜像 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 #查看Docker的版本 wait Block until one or more containers stop, then print their exit codes # 截取容器停止时退出的状态值

    Docker的镜像管理

    搜索镜像:docker search

    [root@hd3 ~]# docker search centos
    NAME(名称)                          DESCRIPTION(描述)                               STARS(下载次数)       OFFICIAL(官方)            AUTOMATED(自动化)
    centos                             The official build of CentOS.                   6115                [OK]                
    ansible/centos7-ansible            Ansible on Centos7                              132                                     [OK]
    consol/centos-xfce-vnc             Centos container with "headless" VNC session…   118                                     [OK]
    jdeathe/centos-ssh                 OpenSSH / Supervisor / EPEL/IUS/SCL Repos - …   115                                     [OK]
    centos/systemd                     systemd enabled base container.                 86                                      [OK]
    docker search 参数说明:
    --automated=true I false:仅显示自动创建的镜像,默认为否; 
    --no-trunc=true | false:输出信息不截断显示,默认为否;
    -s,--stars=X:指定仅显示评价为指定星级以上的镜像,默认为 0,即输出所有镜像。
    例如,搜索所有自动创建的评价为 3+的带 nginx 关键字的镜像,如下所示:
    
    [root@hd3 ~]# docker search --automated -s 3 nginx 
    docker search 其它用法

    获取镜像:docker pull 或 docker image pull

    从官方的Docker Hub网站上拉去镜像:

    docker    pull    [选项]    [Docker    Registry地址]<仓库名>:<标签>
    [root@hd3 ~]# docker pull centos
    Using default tag: latest
    latest: Pulling from library/centos
    6910e5a164f7: Pull complete 
    Digest: sha256:4062bbdd1bb0801b0aa38e0f83dece70fb7a5e9bce223423a68de2d8b784b43b
    Status: Downloaded newer image for centos:latest
    docker.io/library/centos:latest

    查看镜像:docker images 或 docker image ls

    [root@hd3 ~]# docker images
    REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
    centos              latest              831691599b88        5 weeks ago         215MB
    仓库名 标签 镜像ID 创建时间 大小

    删除镜像:docker rmi

    docker    rmi    [选项]    <镜像1>    [<镜像2>    ...]
    [root@hd3 ~]# docker rmi centos
    Untagged: centos:latest
    Deleted: sha256:831691599b88ad6cc2a4abbd0e89661a121aff14cfa289ad840fd3946f274f1f
    Deleted: sha256:eb29745b8228e1e97c01b1d5c2554a319c00a94d8dd5746a3904222ad65a13f8

    导出镜像:docker save 或 docker image save

     如果要导出镜像到本地,提供给另一台机器使用,可以使用docker save 或 docker image save 命令

    [root@hd3 ~]# docker image save centos > /tmp/docker_centos.tar
    [root@hd3 ~]# ll /tmp/docker_centos.tar 
    -rw-r--r--. 1 root root 222584320 Jul 25 08:15 /tmp/docker_centos.tar

    导入镜像:docker load 或 docker image load

    [root@hd3 ~]# docker image load < /tmp/docker_centos.tar 
    Loaded image: centos:latest

    给镜像打标签: docker tag 原标签 新标签 或 docker image tag 原标签 新标

    [root@hd3 ~]# docker image ls  # 打标签前
    REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
    centos              latest              831691599b88        5 weeks ago         215MB
    [root@hd3 ~]# docker image tag centos:latest centos:1.1   # 进行打标签
    [root@hd3 ~]# docker image ls  # 打标签后
    REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
    centos              1.1                 831691599b88        5 weeks ago         215MB
    centos              latest              831691599b88        5 weeks ago         215MB

    Docker的容器管理

    创建容器和启动容器: docker create/run

    创建容器有两种方式一是只创建不启动,二是创建并启动。因为docker的轻量级高,基本上docker是随时用随时删。

    (1)创建不启动

    docker create

    [root@hd3 ~]# docker create -it centos /bin/bash  # 创建容器
    0043b4f5bdafb79a479e7eee1ef0049b1d1d97c3c8961dc26f219872340c220b
    [root@hd3 ~]# docker ps -a  # 查看容器
    CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
    0043b4f5bdaf        centos              "/bin/bash"         7 seconds ago       Created                                 heuristic_kalam
    (ID) (镜像名) (命令) (创建时间) (状态) (端口信息) (容器名) [root@hd3
    ~]# docker start 0043b4f5bdaf # 根据ID启动容器 0043b4f5bdaf [root@hd3 ~]# docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 0043b4f5bdaf centos "/bin/bash" 35 seconds ago Up 11 seconds heuristic_kalam [root@hd3 ~]# docker attach 0043b4f5bdaf # 根据ID进入容器 [root@0043b4f5bdaf /]# ls bin dev etc home lib lib64 lost+found media mnt opt proc root run sbin srv sys tmp usr var [root@0043b4f5bdaf /]# ps -ef UID PID PPID C STIME TTY TIME CMD root 1 0 0 00:35 pts/0 00:00:00 /bin/bash root 16 1 0 00:36 pts/0 00:00:00 ps -ef [root@0043b4f5bdaf /]# exit # 退出 exit

    (2)创建并启动

    [root@hd3 ~]# docker run centos /bin/echo 'hello world'   # 创建容器执行后直接退出并关闭容器
    hello world
    [root@hd3 ~]# docker run --name mydocker -it centos /bin/bash  # 创建容器并进入容器
    [root@9b53b30d9184 /]# 
    [root@9b53b30d9184 /]# pwd
    /
    [root@9b53b30d9184 /]# ls
    bin  dev  etc  home  lib  lib64  lost+found  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var

    参数说明:

    -i, --interactive 交互式
    -t, --tty 分配一个伪终端
    -d, --detach 运行容器到后台
    -a, --attach list 附加到运行的容器
    --dns list 设置DNS服务器
    -e, --env list 设置环境变量
    --env-file list 从文件读取环境变量
    -p, --publish list 发布容器端口到主机
    -P, --publish-all 发布容器所有EXPOSE的端口到宿主机随机端口
    -h, --hostname string 设置容器主机名
    --ip string 指定容器IP,只能用于自定义网络
    --link list 添加连接到另一个容器
    --network 连接容器到一个网络
    --mount mount 挂载宿主机分区到容器
    -v, --volume list 挂载宿主机目录到容器
    --restart string,容器退出时重启策略,默认no [always|on-failure]
    --add-host list 添加其他主机到容器中/etc/hosts
    -m,--memory 容器可以使用的最大内存量
    --memory-swap 允许交换到磁盘的内存量--memory-swappiness=<0-100> 容器使用SWAP分区交换的百分比(0-100,默认为-1--memory-reservation 内存软限制,Docker检测主机容器争用或内存不足时所激活的软 限制,使用此选项,值必须设置低于—memory,以使其优先
    --oom-kill-disable当宿主机内存不足时,内核会杀死容器中的进程。建议设置了memory选项再禁用OOM。如果没有设置,主机可能会耗尽内存
    --cpus 限制容器可以使用多少可用的CPU资源
    --cpuset-cpus 限制容器可以使用特定的CPU
    --cpu-shares  此值设置为大于或小于默认1024值,以增加或减少容器的权重, 并使其可以访问主机CPU周期的更大或更小比例
    
    docker run/create 创建容器常用选项

    docker run 创建容器时,Docker 后台的流程是:

    1. 检查本地是否存在指定的镜像,如果不存在就从远程公有仓库下载

    2. 利用镜像创建一个容器,并启动该容器

    3. 分配一个文件系统给容器,并在只读的镜像层外面挂载一层可读写层

    4. 从宿主主机配置的网桥接口中桥接一个虚拟接口到容器中

    5. 从网桥的地址池配置一个IP地址给容器

    6. 执行用户指定的运用程序

    7. 执行完毕后容器被自动终止

    查看容器: docker ps

    [root@hd3 ~]# docker ps # 查看已经启动的容器
    CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
    9b53b30d9184        centos              "/bin/bash"         22 minutes ago      Up 22 minutes                           mydocker
    [root@hd3 ~]# docker ps -a # 查看所有容器
    CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS                      PORTS               NAMES
    9b53b30d9184        centos              "/bin/bash"              22 minutes ago      Up 22 minutes                                   mydocker
    863635a278d9        centos              "/bin/echo 'hello wo…"   23 minutes ago      Exited (0) 23 minutes ago                       crazy_goodall
    0043b4f5bdaf        centos              "/bin/bash"              32 minutes ago      Exited (0) 31 minutes ago                       heuristic_kalam

    停止容器: docker stop

    除了使用docker stop来停止容器,当Docker容器中指定的应用终结时,容器也会自动终结,例如启动一个终端容器,用户通过exit或Ctrl+d来退出终端时,都会停止容器。

    [root@hd3 ~]# docker ps
    CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
    9b53b30d9184        centos              "/bin/bash"         27 minutes ago      Up 27 minutes                           mydocker
    [root@hd3 ~]# docker stop mydocker  # 后面即可以是容器名也可以是容器ID
    mydocker

    进入容器: docker exec/attach

    外面使用docker create创建容器或者使用docker run -d创建容器时,容器是在后台运行的,如果需要进入这一个容器,docker内置的方法有exec和attach,还有一些工具也可以达到这个

    效果,如nsenter。

    方式一: attach

    [root@hd3 ~]# docker ps -a # 查看有哪些容器,根据状态发现全部都已经停止
    CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS                      PORTS               NAMES
    9b53b30d9184        centos              "/bin/bash"              33 minutes ago      Exited (0) 5 minutes ago                        mydocker
    863635a278d9        centos              "/bin/echo 'hello wo…"   34 minutes ago      Exited (0) 34 minutes ago                       crazy_goodall
    0043b4f5bdaf        centos              "/bin/bash"              43 minutes ago      Exited (0) 42 minutes ago                       heuristic_kalam
    [root@hd3 ~]# docker start mydocker  # 启动容器
    pmydocker
    [root@hd3 ~]# docker ps 
    CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
    9b53b30d9184        centos              "/bin/bash"         34 minutes ago      Up 5 seconds                            mydocker
    [root@hd3 ~]# docker attach mydocker  # 进入容器
    [root@9b53b30d9184 /]# ls
    bin  dev  etc  home  lib  lib64  lost+found  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var

    注意: 使用这种方式进入容器有两个很大的缺点:

      1. 当我们进行退出时,容器会自动结束。

      2. 当第一个用户进入容器后,运行一个阻塞的命令时,第二个用户是无法进入容器的,所以尽量不要使用该方式。

    方式二:exec(推荐使用)

    exec方式是不会出现attach类似的问题,如下:

    [root@hd3 ~]# docker start mydocker  # 启动docker
    mydocker
    [root@hd3 ~]# docker exec -it mydocker /bin/bash     # 进入容器
    [root@9b53b30d9184 /]# ls
    bin  etc   lib      lost+found  mnt  proc  run   srv  tmp  var
    dev  home  lib64  media       opt  root  sbin  sys  usr
    [root@9b53b30d9184 /]# exit   # 退出
    exit
    [root@hd3 ~]# docker ps  # 查看,发现容器没有退出
    CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
    9b53b30d9184        centos              "/bin/bash"         42 minutes ago      Up 36 seconds                           mydocker

    方式三:nsenter工具

    nsenter是启动一个新的shell进程(默认是/bin/bash),同时会把新的进程切换和目标进程相同的命名空间,这样就相当于进入了容器的内部,nsenter要正常工作需要root的权限。

    [root@hd3 ~]# yum intall -y util-linux # 安装工具
    [root@hd3 ~]# docker ps -a
    CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS                      PORTS               NAMES
    9b53b30d9184        centos              "/bin/bash"              48 minutes ago      Up 6 minutes                                    mydocker
    863635a278d9        centos              "/bin/echo 'hello wo…"   48 minutes ago      Exited (0) 48 minutes ago                       crazy_goodall
    0043b4f5bdaf        centos              "/bin/bash"              58 minutes ago      Exited (0) 57 minutes ago                       heuristic_kalam
    
    [root@hd3 ~]# 
    [root@hd3 ~]# docker inspect -f "{{.State.Pid}}" mydocker # 获取容器运行的进程ID
    30380
    [root@hd3 ~]# nsenter -t 30380 -m -u -i -n -p  # 根据进行ID进入容器
    [root@9b53b30d9184 /]# ls
    bin  dev  etc  home  lib  lib64  lost+found  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var
    [root@9b53b30d9184 /]# pwd
    /
    [root@9b53b30d9184 /]# exit
    logout
    [root@hd3 ~]# docker ps 
    CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
    9b53b30d9184        centos              "/bin/bash"         49 minutes ago      Up 8 minutes                            mydocker

    由于上面两条命令都太长,不方便,所以我们编写一个脚本进入,只需在脚本后面跟容器ID或者容器名字即可:

    [root@hd3 ~]# cat in_docker.sh 
    #!/bin/bash
    # Use nsenter to access docker
    
    docker_in() {
        NAME_ID=$1
        PID=$(docker inspect -f "{{.State.Pid}}" $NAME_ID)
        nsenter -t $PID -m -u -i -n -p
    }
    
    docker_in $1
    
    [root@hd3 ~]# docker ps
    CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
    9b53b30d9184        centos              "/bin/bash"         56 minutes ago      Up 14 minutes                           mydocker
    [root@hd3 ~]# ./in_docker.sh mydocker
    [root@hd3 ~]# 
    [root@hd3 ~]# vim in_docker.sh 
    [root@hd3 ~]# ./in_docker.sh mydocker
    [root@9b53b30d9184 /]# ls
    bin  dev  etc  home  lib  lib64  lost+found  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var

    删除容器

    可以使用docker rm 来删除一个处于终止状态的容器,如下:

    [root@hd3 ~]# docker ps -a
    CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS                         PORTS               NAMES
    9b53b30d9184        centos              "/bin/bash"              59 minutes ago      Up 17 minutes                                      mydocker
    863635a278d9        centos              "/bin/echo 'hello wo…"   59 minutes ago      Exited (0) 59 minutes ago                          crazy_goodall
    0043b4f5bdaf        centos              "/bin/bash"              About an hour ago   Exited (0) About an hour ago                       heuristic_kalam
    [root@hd3 ~]# docker rm 863635a278d9  # 删除容器
    863635a278d9
    [root@hd3 ~]# docker ps -a
    CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS                         PORTS               NAMES
    9b53b30d9184        centos              "/bin/bash"         59 minutes ago      Up 18 minutes                                      mydocker
    0043b4f5bdaf        centos              "/bin/bash"         About an hour ago   Exited (0) About an hour ago                       heuristic_kalam

    如果要删除一个运行中的容器,可以添加 -f 参数。 Docker会发送 STGKILL信号给容器,再进行删除。

    清理所有处于终止状态的的容器(慎用

    [root@hd3 ~]# docker ps -a   
    CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS                           PORTS               NAMES
    0ca1770a1fd0        centos              "/bin/bash -c 'while…"   About an hour ago   Exited (137) About an hour ago                       ecstatic_wu
    4d18a48ee315        centos              "/bin/bash"              About an hour ago   Exited (0) About an hour ago                         amazing_herschel
    b3918347393a        centos              "/bin/echo 'Hello Wo…"   About an hour ago   Exited (0) About an hour ago                         competent_lovelace
    [root@hd3 ~]# docker rm $(docker ps -a -q)   # 获取全部容器的ID,进行删除 
    0ca1770a1fd0
    4d18a48ee315
    b3918347393a
    [root@hd3 ~]# docker ps -a 
    CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
    [root@server ~]# docker ps
    CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES

    导出和导入容器

    某些时候,需要将容器从一个系统迁移到另外一个系统,此时可以使用Docker的导入和导出功能。这也是Docker 自身提供的一个重要特性.

    导出容器: docker export

    如果要导出本地某个容器,可以使用 docker export 命令,导出容器是指导出一个已经创建的容器到一个文件,不管此时这个容器是否处于运行状态。export后面跟需要导出的 容器ID 或者 容器名字 都可以

    [root@hd3 ~]# docker export mydocker >docker_centos.tar  # 导出容器
    [root@hd3 ~]# ls docker_centos.tar 
    docker_centos.tar

    导入容器: docker import

    导出的文件又可以使用 docker import 命令导入变成镜像,例如

    [root@hd3 ~]# cat docker_centos.tar | docker import - test/centos:7.1  # 将导入的容器加载为镜像文件
    sha256:f29fdf78e362b8bdbcc2e67ed9c4c1e54be8dba9e0351f866c68bf2a21f9af43
    [root@hd3 ~]# docker images
    REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
    test/centos         7.1                 f29fdf78e362        5 seconds ago       215MB
    centos              1.1                 831691599b88        5 weeks ago         215MB
    centos              latest              831691599b88        5 weeks ago         215MB

    Docker的数据管理

     Docker容器中管理数据主要有两种方式:

    1. 数据卷(Data volumns)

    2. 数据卷容器(Data volumes containers)

    数据卷

    数据卷是一个可供一个或多个容器使用的特殊目录,它绕过UFS,可以提供很多有用的特性:

    1. 数据卷可以在容器之间共享或重用

    2. 对数据卷的修改会立马生效

    3. 对数据卷的更新,不会影响镜像

    4. 数据默认会一直存在,即使容器被删除

    管理卷: docker volumn:

    [root@hd3 ~]# docker volume create myvolume  # 创建一个volumn
    myvolume
    [root@hd3 ~]# docker volume inspect myvolume  # 查看volun的详细信息
    [
        {
            "CreatedAt": "2020-07-25T10:13:15+08:00",
            "Driver": "local",
            "Labels": {},
            "Mountpoint": "/var/lib/docker/volumes/myvolume/_data",  # 可以看到创建的volumn在宿主机的目录
            "Name": "myvolume",
            "Options": {},
            "Scope": "local"
        }
    ]
    [root@hd3 ~]# docker volume ls   # 查看有哪些volumn
    DRIVER              VOLUME NAME
    local               6e5600ecd418b0200a632f168c297f2af817b779d51ff96a570a38405dee4e94
    local               8d207d24425a6165714c19bacd29d33b8673ca22fc6d66bba8267cee508cf56a
    local               32f4402df57e777e339b506b8e37e3e52c2b836c37b11d185a1b4d736eeeaf1d
    local               mysql-vol
    local               myvolume

    创建容器时挂载一个volumn:

    --mount参数:
    src:数据卷名字 dst:需要挂载的目录路径 注意:如果没有指定卷,则自动创建

    如下实例:

    [root@hd3 ~]# docker run -d -it --name myvolume --mount src=myvolume,dst=/data centos
    253866f5e1a65819339f14712e2fffc36cc26ad640bc1bf36499b0d0beedfe68
    [root@hd3 ~]# docker exec -it myvolume /bin/bash
    [root@253866f5e1a6 /]# ls  # 可以看到有data目录
    bin  data  dev    etc  home  lib    lib64  lost+found  media  mnt  opt  proc  root    run  sbin  srv    sys  tmp  usr  var

    可以在宿主机上创建文件,然后再查看docker容中是否存在文件:

    [root@hd3 _data]# pwd
    /var/lib/docker/volumes/myvolume/_data
    [root@hd3 _data]# ls
    [root@hd3 _data]# 
    [root@hd3 _data]# echo aaa >test.txt
    [root@hd3 _data]# ls
    test.txt
    
    # 在容器中
    [root@253866f5e1a6 data]# ls  # 一开始没有
    [root@253866f5e1a6 data]# 
    [root@253866f5e1a6 data]# pwd  
    /data
    [root@253866f5e1a6 data]# ls  # 宿主机创建后有该文件
    test.txt

     删除数据卷: docker volume rm

    Docker不会在容器被删除后就自动删除数据卷,而且如果我们要删除数据卷的话,就必须先将数据卷的容器停止, 删除后,才能删除数据卷.

    [root@wallace ~]# docker rm -f myvolume
    myvolume
    [root@wallace ~]# docker volume rm myvolume
    myvolume

    挂载主机目录作为数据卷

    使用-v参数也可以指定挂载一个本地主机的目录到容器中

    [root@wallace ~]# docker run -d -it --name web -v /webapp:/opt/webapp centos # 创建一个名字叫web的容器,并将宿主机的/webapp目录 挂载到容器的/opt/webapp
    64b8d2c90226f0fda4802d4a846bd6acb1d4643d0b0632f7478d013a7a200a44
    [root@wallace ~]# cd /webapp/
    [root@wallace webapp]# echo "hellow" >> /webapp/index.html  # 宿主机追加文件
    [root@wallace webapp]# docker exec -it web /bin/bash
    [root@64b8d2c90226 /]# cat /opt/webapp/index.html   # 进入容器查看文件
    hellow

    挂载一个宿主文件作为数据卷

    -v 参数也可以从主机挂载单个文件到容器中

    [root@wallace ~]# docker run --rm -it -v ~/wallace.log:/wallace.log centos /bin/bash # 创建一个容器,并将宿主基地wallace.log文件挂在到容器中,
    --rm表示容器退出就删除

    数据卷容器

     如果有一个持续更新的数据需要在容器之间共享,最好的方法是创建一个数据卷容器. 数据卷容器其实就是一个正常的容器,专门用来提供数据卷供其他容器挂载.

    [root@wallace ~]# docker run -d -v /dbdata --name dbdata centos  # 创建一个名为dbdata的数据卷容器, 在容器的目录是dbdata
    2669e77f93f62ccb5018ac4563008ee29d1a7a6ac39c8bdbcb3fbfa8c1d1559a
    [root@wallace ~]# 
    [root@wallace ~]# docker ps -a  # 注意创建的数据卷容器是无需启动的
    CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS                      PORTS               NAMES
    2669e77f93f6        centos              "/bin/bash"         54 seconds ago      Exited (0) 53 seconds ago                       dbdata
    64b8d2c90226        centos              "/bin/bash"         17 minutes ago      Up 17 minutes                                   web
    dc78600663be        centos              "/bin/bash"         39 minutes ago      Up 38 minutes                                   mycentos
    [root@wallace ~]# docker run -d -it --volumes-from dbdata --name db1 centos  # 创建一个db1容器,将dbdata数据卷挂载到db1中
    26fb95b8ecb7051ad91210d6f5331a4e8fa16efdad5522bd455408da27815153
    [root@wallace ~]# docker exec -it db1 /bin/bash  # 进入容器
    [root@26fb95b8ecb7 /]# ls  # 查看可以发现可以遭到dbdata目录
    bin  dbdata  dev  etc  home  lib  lib64  lost+found  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var
    [root@26fb95b8ecb7 /]# touch  dbdata/file1  # 在目录中创建一个文件,然后退出
    [root@26fb95b8ecb7 /]# exit  
    exit
    [root@wallace ~]# docker run -d -it --volumes-from dbdata --name db2 centos # 创建一个db2容器,将dbdata数据卷挂载的到db2中
    15746e015dc10a9cd58644d783277772e016a9dfc9b2559abc1e8391d108cdd1
    [root@wallace ~]# docker exec -it db2 /bin/bash   # 进入db2容器
    [root@15746e015dc1 /]# ls
    bin  dbdata  dev  etc  home  lib  lib64  lost+found  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var
    [root@15746e015dc1 /]# ls dbdata/file1   # 查看发现可以找到db1创建的容器,说明数据共享完成
    dbdata/file1
    [root@15746e015dc1 /]# exit
    exit

    从上面可以看出可以使用超过一个 --volumes-from 参数来指定从多个容器挂载不同的数据卷,也可以从其他已经挂载了数据卷的容器来级联挂载数据卷,示例:

    [root@wallace ~]# docker run -d -it --name db3 --volumes-from db1 centos # 将db1的数据卷挂载到新创建的db3容器中
    c65346d5f8c23d6d5305ab6b4a5aa9cb5255778c83e4a9a66e44921329ed0dab
    [root@wallace ~]# 
    [root@wallace ~]# docker exec -it db3 /bin/bash  # 进入db3容器,发现可以查找到数据
    [root@c65346d5f8c2 /]# ls /dbdata/file1 
    /dbdata/file1

    注意:使用 --volumes-from 参数所挂载数据卷的容器自己不需要保持在运行状态。如果删除了挂载的容器(包括dbdata、db1和db2),数据卷也不会被自动删除。如果要删除一个数据卷,必须在删除最后一个还挂载着它的容器时使用 docker rm -v 命令来指定同时删除关联的容器。

      

  • 相关阅读:
    蛙蛙推荐:蛙蛙牌正文提取算法
    javascript太牛了,还能模拟函数式编程
    蛙蛙推荐:编写一个服务监控及管理的软件
    蛙蛙推荐:Remoting超时问题及初步解决方案
    WaTu项目简介
    蛙蛙推荐:基于标记窗的网页正文提取算法的一些细节问题
    【蛙蛙推荐】windbg使用小总结
    蛙蛙推荐:windbg里查看DateTime值
    Enterprise Library :数据访问程序块学习1 dodo
    (转)一个带自定义分页,排序功能的DATAGRID控件(公开源码) dodo
  • 原文地址:https://www.cnblogs.com/tashanzhishi/p/13397762.html
Copyright © 2011-2022 走看看