Docker概述
什么是Docker
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 7 (64-bit) CentOS 6.5 (64-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 命令来指定同时删除关联的容器。