Docker, Getting Started and Practical Applied
计划分两部分总结一下Docker的学习。本文先从入门到应用开始,了解Docker并用上它。
0 总结:
本文推荐使用Docker Compose运行和管理容器。
1 概述
1.1 Docker是什么?
Docker是依赖Linux内核,通过建立应用的运行环境,实现虚拟化。其实现方式不是采用硬件级别的虚拟,而是“隔离”。就是通过隔离手段实现软件运行环境的沙箱化。
其底层依赖于Linux的chroot、namespace、cgroup等三种老技术,结合当前系统的Linux内核,建立另一个Linux运行环境,并运行指定软件。试过在Android系统部署Linux分发版(Android也是一个Linux发行版),就是使用了类似的技术。
要注意,Docker的目的不是提供一个完整的虚拟Linux,而是把运行环境和软件组合为服务,去运行和管理。例如Debian官方镜像默认没有提供“服务”(servcie)管理的功能,而是作为一个指定服务的一部分去运行。
参考资料:
- Docker 的底层原理,了解它只需要 5分钟!
https://www.51cto.com/article/644401.html
1.2 为什么要用Docker?
一次建立,到处运行。
- 环境和软件一起打包,不用担心测试环境与正式环境的区别。
- 对于Window平台可以使用WSL运行。
优胜于传统虚拟机。
- 轻,只虚拟环境。
- 快,运行快。
- 小,资源占用小,包括CPU、内存、硬盘等资源。
管理简单。
- 镜像作为模板,容器作为实例。
- 多个容器可以关联组合。
例如,部署多个MySQL数据库,并配置不同的参数作对比,那么直接运行多个MySQL的Docker容器即可,其表现为运行在不同IP的多个MySQL服务。
1.3 基本概念
仓库(Repository)
- 用于存储和分发镜像。
- 例如,Docker官方公共仓库:https://hub.docker.com/search
镜像(Image)
- 容器运行时所需的root文件系统(包括程序、库、资源、配置等文件),以及配置参数(包括匿名卷、环境变量、用户等)。
- 可来理解为容器的模板。其不包含动态数据,构建后不可修改。
容器(Container)
- 简单来说,跟面向对象程序设计中的“类”(镜像)和“实例”(容器)一样。
- 容器包括容器配置、相关文件、相关进程。
1.4 怎样使用?
再次强调,Docker是建立应用的运行环境,不是虚拟机。所以不要在Docker容器里面跑服务,而是把整个Docker容器作为一个服务进行管理和使用。
- 例如启动Dokcer容器时,执行一个启动脚本,运行所需软件。
一般建议把重要数据映射到容器外部的文件系统,避免删除或升级容器时同时删除相关文件,也能减少性能损耗。
- 例如Docker部署MySQL,建议把数据目录映射出来。
- 升级容器时,先下载更新的镜像,再删除该容器,并使用相同的配置文件,建立同名的容器。
1.5 Docker Compose
为了更好地解决多个Docker容器协同部署、工作,诞生了“Docker Compose”。一开始使用“Python”实现的,但到了2.0,Docker官方使用Go重新实现,并以插件形式集成到docker-ce(其软件包名为docker-compose-plugin
)。使用docker compose
命令(代替1.0的docker-compose
命令)进行Docker容器的编排。
Docker Compose另一个的优点是,借助YAML脚本和环境变量,可以轻松配置或修改Docker容器。相比之下,使用docker run
命令部署的Docker容器,修改配置需要重启Docker服务(影响其它Docker容器),相当麻烦。所以建议使用Docker Compose的方式运行Docker容器,而且一般Docker会提供Docker Compose的示例配置文件。
1.6 Kubernetes
Kubernetes也称为K8s,是用于自动部署、扩缩和管理容器化应用程序的开源系统。它将组成应用程序的容器组合成逻辑单元(Pod),以便于管理和服务发现。这部分内容,计划另起一个文章再整理。
- Kubernets官网
https://kubernetes.io/zh-cn/
1.7 参考文档
- Docker 入门教程 - 阮一峰的网络日志
https://www.ruanyifeng.com/blog/2018/02/docker-tutorial.html - Docker — 从入门到实践
https://yeasy.gitbook.io/docker_practice/ - Docker官方文档
https://docs.docker.com/ - Docker Compose overview
https://docs.docker.com/compose/ - 一张脑图整理Docker常用命令
https://segmentfault.com/a/1190000038921337
2 安装部署
2.1 安装
官方安装教程如下:
- Docker Engine installation overview
https://docs.docker.com/engine/install/ - Install Docker Engine on Debian
https://docs.docker.com/engine/install/debian/
针对Debian或Ubuntu,总结如下:
- 推荐使用Docker官方APT仓库进行安装。一般先卸载通过系统仓库安装的自带Docker引擎。
- 安装Docker CE版,即Community Edition(社区版,免费)。
- 安装docker-compose插件:
sudo apt install docker-compose-plugin
。
2.2 配置
Docker服务的配置,主要分为命令行参数和配置文档。
详见官方说明文档:
由于这里以SystemD服务的方式运行Docker服务,所以采用配置文件的方式进行配置。在采用SystemD的Linux发行版上(例如Ubuntu 16.04+、Debian 8+、CentOS 7等),对应配置文件为/etc/docker/daemon.json
(如没有该文件,需要自行创建)。
修改并保存daemon.json
后,一般无需重启Docker服务,发送reload信号即可。如下:
sudo systemctl daemon-reload
sudo systemctl reload docker.service
2.3 设置“仓库”镜像(mirror)网站
如果访问官方“仓库”比较慢,可以使用中国的镜像网站。在配置文件/etc/docker/daemon.json
中加入:
{
"registry-mirrors": ["https://hub-mirror.c.163.com/"]
}
其它可用的加速镜像可参考:
2.4 设置代理
这里是为了解决Docker不能访问第三方“仓库”的网址,导致不能拉取相关“镜像”文件。例如gcr.io/cadvisor/cadvisor
.
在配置文件/etc/docker/daemon.json
中加入:
{
"proxies": {
"http-proxy": "http://proxy.example.com:80",
"https-proxy": "https://proxy.example.com:443",
"no-proxy": "*.test.example.com,.example.org,.163.com,192.168.0.0/24,127.0. 0.0/8"
}
}
其中,http-proxy
和https-proxy
是设置相应的HTTP代理服务,no-proxy
是设置不走代理的域名或IP。
2.5 设置权限阻隔
默认情况下,“容器”中的进程以root用户权限运行,与“宿主机”中的root是同一个用户。这就意味着一旦“容器”中的进程有了适当的机会,它就可以控制“宿主机”上的一切。
解决方法有两种,一种是使用非root用户运行容器,另一种是用户命名空间(user namespace)方式。
关于用户命名空间的设置,参考下文:
- Docker中使用userns-remap做用户命名空间
https://blog.csdn.net/zyy247796143/article/details/114386484
3 使用
3.1 运行“容器”
到“仓库”找所需“镜像”,下载“镜像”后运行对应的“容器”。直接执行“docker run”时,如果本地没有相关“镜像”,会自动在Docker官方“仓库”下载,然后创建“容器”并运行。
一般使用软件官方提交的“镜像”,若要使用第三方“镜像”,最好确认清楚是否安全。
下面以部署Debian容器为例:
# 搜索Debian“镜像”
docker search debian
# 查看“镜像”版本,最好是访问docker官网。例如Debian镜像的版本:https://registry.hub.docker.com/_/debian/tags
# 下载Debian“镜像”。格式是,“镜像”名称:版本名称。如果不填版本名称,默认是Latest。
docker image pull debian:stable
# 列出所有已下载的“镜像”,包括隐藏的。以下三个命令的效果是一样的。
docker image ls -a
docker image list -a
docker images -a
# 查看正在运行的“容器”。以下三个命令的效果是一样的,推荐第一个。
docker container ls
docker container ps
docker container list
# 查看所有“容器”,包括未运行。
docker container ls -a
# 创建并运行“容器”。名为“debian-test”,映射两个端口(本机50080->“容器”40080,本机51080->“容器”41080),并把本地“/opt/docker-files/debian-test/opt”目录映射到“容器”的“/opt”目录。
docker run -it --name debian-test -p 50080:40080 -p 51080:41080 -v /opt/docker-files/debian-test/opt:/opt debian:stable
# 查看“容器”运行日志,检查是否报错
docker logs debian-test
3.2 进入“容器”
进入“容器”。可以使用attach
或exec
命令,但建议使用exec
并运行一个新的Bash,避免退出时影响“容器”当前运行的程序。
attach
命令。适合“容器”正在运行具有命令行交互的程序,比如“Bash”。以下两个命令是一样的。
# 两个命令是一样的
docker attach debian-test
docker container attach debian-test
要注意,使用attach
命令进入“容器”并输入“exit”进行退出时,就等于Bash程序结束执行,“容器”随之停止运行。解决方案:
- 方案1,“docker attach”进入容器后,按Ctrl + P + Q退出。
方案2,进入容器时,加入参数“--sig-proxy=false”,退出时使用“exit”命令而不停止容器。
- 例如:docker attach --sig-proxy=false debian-test
exec
命令。打开一个具有命令行交互的程序,即进入“容器”。
# 两个命令是一样的,运行Bash并进入
docker exec -it debian-test /bin/bash
docker container exec -it debian-test /bin/bash
# 使用root用户运行Bash,并设置字符编码
docker exec -u root -it debian-test env LANG=C.UTF-8 /bin/bash
退出“容器”就等于退出当前运行的Bash,对“容器”正在运行的程序无影响。
3.4 管理“容器”
# 启动“容器”
docker container start debian-test
# 停止“容器”
docker container stop debian-test
# 重启“容器”
docker container restart debian-test
# 删除“容器”
docker container rm debian-test
3.5 复制“容器”
主要思路是,把指定“容器1”生成“镜像A”,再用“镜像A”创建“容器2”,实现把“容器1“复制为”容器2“。
注意:生成“镜像”时,“容器”外部的文件,不会打包进“镜像”文件。需要手工复制这些文件,并设置映射。
假设已创建“容器”:debian-test,需要复制为另一个“容器”:debian-test2。
# 把“容器” debian-test,生成“镜像”文件
docker export debian-test > /opt/docker_image_debian-test.tar
# 引入“镜像”,并命名为 debian-test:v1
docker import /opt/docker_image_debian-test.tar debian-test:v1
# 创建另一个“容器” debian-test2
docker run -itd --name debian-test2 -p 50081:40080 -p 51081:41080 -v /opt/docker-files/debian-teset2/opt:/opt debian-test:v1 /bin/bash
3.5 Dokcer图形化管理
Docker Desktop下载地址和安装介绍:
- Docker Desktop
https://docs.docker.com/desktop/ - Install Docker Desktop on Windows
https://docs.docker.com/desktop/install/windows-install/
4 使用Docker Compose
Docker Compose是以“项目”(project)作为管理单元。一个项目,是由一个或多个“服务”(service,即“容器”)组合而成。
4.1 使用
把Compose配置文件存放到指定目录,进入该目录,并执行docker compose up
,即可启动。
4.2 命令说明
格式:docker compose [可选项] 命令
。“可选项”和“命令”的说明如下:
可选项 | 说明 |
---|---|
--ansi string | 控制何时打印 ANSI 控制字符。string的可选值为"never"、"always"、"auto",默认为"auto"。 |
--compatibility | 以向后兼容模式运行 compose。 |
--env-file stringArray | 指定备用环境文件。 |
-f, --file stringArray | Compose配置文件。 |
--parallel int | 控制最大并行度,-1 为无限制。默认-1。 |
--profile stringArray | 指定要启用的配置文件。 |
--project-directory string | 指定备用工作目录。默认:首先采用所配置的第一个Compose文件的路径。 |
-p, --project-name string | 项目名称。 |
命令 | 说明 |
---|---|
build | 构建或重新构建服务 |
config | 以规范格式粘贴、解析和呈现Compose配置文件 |
cp | 在服务容器和本地文件系统之间复制文件或文件夹 |
create | 为服务创建容器 |
down | 停止并移除容器、网络 |
events | 从容器接收实时事件 |
exec | 在正在运行的容器中执行命令 |
images | 列出创建的容器使用的镜像 |
kill | 强制停止服务容器 |
logs | 查看容器的输出 |
ls | 列出正在运行的Compose项目 |
pause | 暂停服务 |
port | 打印端口绑定的公共端口 |
ps | 列出容器 |
pull | 拉取服务镜像 |
push | 拉取服务镜像 |
restart | 重启服务容器 |
rm | 删除停止的服务容器 |
run | 在服务上运行一次性命令 |
start | 启动服务 |
stop | 停止服务 |
top | 显示正在运行的进程 |
unpause | 取消暂停服务 |
up | 创建并启动容器 |
version | 显示 Docker Compose 版本信息 |