如何优雅地应用 Docker
很久很久以前,就已经尝试过应用 Docker 。然而因为没有足够的能源学习,导致屡次大功告成(就像学 vim 一样)。
终于,在想要应用 gitbook 转换开源书籍时,被放弃保护的 gitbook-cli 给教育了。因而重燃起学习 Docker 的能源。
原文公布于 集体博客
同步备份至知否、掘金、知乎、腾讯云、微信公众号、哔哩哔哩
如果有谬误斧正或探讨,倡议在原博客评论,多平台可能无奈保障及时回复。同时无奈保障各平台内容放弃最新。
Docker 是什么
容器和虚拟机
容器和虚拟机不同,或者说除了看上去像,他们齐全是两个没有关系的货色。
虚拟机是在计算机中模仿另一个计算机的技术,重点在于模仿和另一个计算机。因而虚拟机须要先将物理机的硬件进行封装,并部署一个独立的操作系统。独立的操作系统调用模仿的硬件,实现各种性能。对于运行在虚拟机内的零碎来说,它仿佛就在一个真正的物理机上运行,不会受到过多的限度。
沙盒,其用处是隔离运行环境,而非模仿计算机。因而它不须要虚拟化硬件,也不须要装置独立的操作系统。晚期的沙盒(如 Sandboxie)往往用于运行一些不被信赖的软件,在计算机平安等方面大放异彩。运行在沙盒中的软件,即便是攻击性很强的病毒,依然很难危害到物理机(但就如同虚拟机一样,沙盒也存在被穿透的危险)。能够将其了解成依然执行在物理机的宿主零碎之中,然而外部所有程序的零碎调用都被沙盒截取(就像 proxychains 能够批改任意子过程的网络连接一样)替换为本人的虚构的零碎调用。当外部的程序须要写出、读入一个文件(狭义上所有货色都是文件)时,实际上操作的是虚构的文件并不会影响宿主零碎。
在较新版本的 Windows 中,有一个叫做 Sandbox 的利用,点击后会弹出一个窗口,窗口外部是一个 Windows 零碎,这就是一个 Windows 的沙盒。
而容器则相似于沙盒的增强版,其容许通过配置有目的性地容许某些穿透操作(如将容器端口映射到宿主零碎、拜访宿主零碎的某个目录)。同时,也容许在容器中部署一个与宿主零碎类似但不同的操作系统(这里次要指能够诸如在 Arch Linux 应用 Ubuntu 镜像,然而如果是 Windows,其无奈间接应用 Linux 镜像,须要先应用 Hyper-V 虚构一个 Linux)。
所以,绝对于虚拟机,容器更为轻量级(只是替换子过程的零碎调用,而非模仿硬件且装置残缺的操作系统);绝对于沙盒,容器可操作性更多(能够有选择性地容许与宿主零碎进行交互)。因而也能够将沙盒了解为一种非凡的容器。
这也就是 Docker 在开发中受到宽泛推崇的起因,它能够隔离出一个自定义环境、部署快、容许有选择地穿透。刚好满足开发和部署过程中容易遇到的环境不统一问题。
Docker 的分层
Docker 在上述容器的根底上,还有额定的一些长处。在 Docker 中,操作是分层的。试想,你是一个前端工程师,你有两个我的项目须要开发——React 我的项目、Vue 我的项目。假如他们都运行于 Ubuntu,并且应用雷同版本的 NodeJS。如果应用下述的图中的链式关系,用户须要保护两份 Ubuntu 环境、两份 NodeJS 环境。而在 Docker 中,对于这些共有的内容,将会将其划分为公共的层。也即,他们都基于 Ubuntu 下的 NodeJS 镜像生成,而非从头开始生成。将会共用后面独特须要的局部。
目前很多镜像实际上都会应用 Ubuntu 作为操作系统,并且应用官网的一些环境作为开发环境。因而用户可能会应用很多的 Docker 镜像来部署本人的服务, 但实际上因为他们在底层共用了雷同镜像,因而空间占用近似于部署在物理机(只节约了局部 Docker 自身所占用的空间和资源)
该设计原理上很奇妙,但理论应用中,特地是作为镜像的发布者而非使用者,还是须要破费功夫思考设计的。
装置
对于失常环境(如 Windows、Linux)能够间接在官网装置 Docker 即可。
而如果想要在 WSL2 中应用 Docker,则须要参考 Docker Desktop WSL 2 backend 和 Using Docker in WSL2
Docker 分为两局部:服务端、客户端。
所有的容器都会保留、运行在服务端,客户端仅仅用于管制。以 WSL2 为例,实际上 Docker 运行在 Hyper-V 的虚拟机中,客户端在 WSL 中操作 Windows 下的 Docker 管制虚拟机中的 Docker。在大部分状况下可能不须要思考这些关系,然而在须要通过 IP 端口互联时,须要确定到底要连到哪一个局域网 IP。
如果要通过 Docker 连回服务端所在设施,能够应用host.docker.internal
镜像
镜像是对于一些环境的封装(打包好的环境)。能够将其了解成安装包、压缩包,其自身是不可改变的。一般而言,镜像会基于官网提供的一些零碎为根底(如罕用的是 Ubuntu,也能够基于没有操作系统的 scratch),装置相应依赖程序为某些特定程序提供服务。
镜像信息查看
应用docker images
能够获取所有本地存在的镜像,蕴含 5 列信息:
- 镜像名称(蕴含用户名、镜像名)
- 标签(版本)
- 镜像 ID(哈希值)
- 创立工夫(镜像自身创立工夫,而非下载或本地生成工夫)
- 镜像大小(本镜像所有分层总大小)
因为后面提到的分层概念,实际上这里的镜像大小之和应该大于或等于理论占用大小(多个镜像可能蕴含雷同的分层)。
镜像的拉取
如果须要获取某个镜像,能够应用docker pull <用户名>/<镜像名>:<版本号>
。这里用户名和镜像名针对于官网 Docker 仓库,如果省略镜像名,将会从官网保护的镜像中检索;如果省略版本号,将会应用最新版本latest
。
如果须要从公有仓库拉去镜像,则能够间接 pull 对应的 URL
镜像导出、导入
无论是应用 Dockerfile 生成,还是间接从仓库获取分层,都须要破费工夫下载、耗费性能生成。而本地多设施要部署雷同的镜像,也能够间接将整个镜像导出成单文件,再在另一台设施上导入。这样能够更不便地在本地之间传输 Docker 镜像。
导出后的镜像文件相似于 ghost 备份,相当于间接把零碎保留成为一个单文件环境。
export/import
要导出镜像,能够应用docker export [镜像名称] > xxx.tar
。其中镜像名称能够应用用户名/镜像名:标签
,也能够间接指定镜像 ID(只须要前几位即可)。
要将镜像导入 Docker,应用docker import [文件名] [镜像名]
。如果文件名为-
,也能够应用重定向符从 stdin 读入文件。
应用 export/import 将会失落镜像的历史,仅仅保留最终状态的快照(也因而会更小)。一般来说,能够用于公布根底镜像(用户不须要应用历史记录等信息)
save/load
另一种计划则是基于 save/load 命令。导出镜像与export
相似,应用docker save [镜像名称] > xxx.tar
。如果想要导出多个镜像,也能够应用 docker save xxx.tar xxx1 xxx2
。
要从新载入,应用docker load < xxx.tar
。
绝对于后面的 export/import,save/load 更相似于“存档”的概念,其蕴含镜像的所有信息(包含历史),因而也无奈批改镜像名称,同时其反对将多个镜像保留到一个文件中。因而其更实用于同步设施之间的状态。
Dockerfile
Dockerfile 是一种非凡的文件,其能够被docker build
辨认,用于生成镜像。在很多状况下,配置一个环境所须要的可能只是简略的配置,如果每一个环境都导出一份镜像将会消耗大量空间。对于这种状况,只提供一个短短几行的 Dockerfile,由用户设施主动进行配置更为不便。
每一个镜像都是由多个分层形成,每个分层绝对于上一分层也仅仅是通过某个命令进行文件的增删改。因而只有将这些命令保留下来,即可形容一个镜像。而有幸的是,Linux 的各种命令(特地是 busybox),齐全能够实现绝大部分所须要的行为。
以一个启动一个 Nginx 服务,并显示特定页面的镜像为例,只须要如下局部:
FROM nginxRUN echo '<h1>Hello Docker</h1>' > /usr/share/nginx/html/index.html
这里,应用FROM
指定了根底镜像——官网公布的 Nginx 镜像,并在其根底上执行echo '<h1>Hello Docker</h1>' > /usr/share/nginx/html/index.html
。如果对 Nginx 有所理解,应该能够很容易看出这就是批改了 Nginx 的根底页面。
Dockerfile 应用各种操作实现了各种操作
命令 | 解释 | 备注 |
---|---|---|
FROM | 应用的根底镜像 | 除去常见的零碎镜像外,如果只须要运行某个程序,也能够应用不蕴含零碎的 scratch 间接执行二进制程序,以减小镜像大小<br/>一个Dockerfile 能够存在多个FROM ,每个FROM 作为一个构建阶段造成一个独自的镜像(能够应用FROM xxx as xxx 来设定阶段名称,应用docker build --target 只构建该阶段) |
RUN | 要执行的命令 | 其蕴含两种格局RUN <shell 命令> 和RUN ["可执行文件门路","参数1","参数2",...] 。<br/>因为每一行命令都会被认为是独自的一层,因而通常须要尽可能应用& 来连贯多个命令 |
COPY | 复制文件 | 蕴含两种格局COPY <源门路> ... <指标门路> 和COPY ["<源门路1>", ..."<指标门路>"] <br/>能够同时复制多个文件,且反对通配符。复制后会保留权限等元数据 |
ADD | 减少文件 | 某种非凡模式的复制,其源门路能够是互联网上的文件地址。因为其会在网络下载,因而能够实时更新,但也会使得构建缓存生效 |
CMD | 容器启动默认命令 | 与RUN 雷同的两种模式,用于指定 Docker 启动后的默认命令(可能会被docker run 笼罩掉)<br/>因为 Docker 容易的存活依赖于前台程序,因而诸如启动 Nginx 须要间接执行 nginx 二进制文件,而不应该应用systemctl |
ENTRYPOINT | 入口点 | 与RUN 雷同的两种格局。与CMD 性能类似,在配置ENTRYPOINT 后,默认的执行程序将会形如<ENTRYPOINT> "<CMD>" 。<br/>如果镜像性能为调用某个程序,并传递某个参数,能够应用该计划来在docker run 时配置参数(可参考curl 镜像)<br/>用户能够用--entrypoint 笼罩 |
ENV | 设置环境变量 | 格局为ENV <key> <value> 和ENV <key1>=<value1> <key2>=<value2> |
ARGS | 构建参数 | 与ENV 相似,但ARGS 设置的环境变量只会在构建期间存在,用户能够应用docker build --build-arg <参数值>=<值> 笼罩 |
VOLUME | 匿名卷定义 | 格局为VOLUME ["门路1","门路2"...] 和VOLUME <门路> 。事后将可能被批改的目录挂载为匿名卷,如果用户在未挂载时删除,依然能够保留数据 |
EXPOSE | 申明端口 | EXPOSE <端口1> [<端口2>...] ,申明将会映射出的端口。<br/>仅仅只是申明,不会进行任何映射操作,用户须要应用-p <宿主端口>:<容器端口> 指定映射,或应用-P 主动随机映射 |
WORKDIR | 指定工作目录 | Dockerfile 的每一行都处于独立的运行环境,因而在cd 只会作用于单个RUN 。如果须要批改后续所有命令的执行目录,应用WORKDIR <门路> |
USER | 指定运行用户 | 切换到某个已存在的用户执行后续命令,须要应用RUN 事后建设好用户 |
HEALTCHECK | 健康检查 | 查看容器衰弱状态,有两种模式HEALTHCHECK [选项] CMD <命令> 和HEALTCHECK NONE 。别离为设置查看的命令与不应用查看<br/>参数包含距离(--interval )、时长(--timeout )、次数(--retries ),依据完结码判断是否存活 |
ONBUILD | 只在构建上级镜像时执行 | 该局部不会在构建以后镜像时执行,只会在构建以该镜像为根底镜像时会执行 |
上述命令中,所有形如["aaa","bbb","ccc"]
的命令都应该应用双引号"
,因为这些命令将会以 JSON 的模式被读入 Docker,而 JSON 规定的字符串应用双引号。
下面有提到应该尽可能应用&
来连贯命令。以apt install
为例,只管大部分状况下能够间接下载二进制文件,然而某些程序可能须要本地编译,从而产生很多两头缓存的文件。如果不及时清理,则会将这些缓存也存入分层数据中(而这显然是不用的)。因而,大部分状况下,RUN
应该是相似上面的模式
RUN buildDeps='gcc libc6-dev make' && apt-get update \ && apt-get install -y $buildDeps \ && wget -I xxx.tar \ && tar -xzf xxx.tar -C xxx \ && make -C xxx \ && make -C xxx install \ && rm -rf xxx \ && rm xxx.tar \ && apt-get purge -y --autoremove $buildDeps
在编写 Dockerfile 的时候,必须时刻明确本人的目标——不是在写 Shell,而是在执行某个明确的操作,应该防止在分层中引入无关的内容。
对于一个曾经编写实现的 Dockerfile 文件,应用docker build -f ./dockerfile -t xxx:v1 .
来将其生成为一个镜像。
这里,-f
参数能够疏忽,疏忽后默认应用当前目录的Dockerfile
文件;-t
参数也能够疏忽,示意不指定名称和标签;最初的.
示意构建上下文目录,也即 Dockerfile 中COPY
或ADD
命令的绝对目录。
Docker 在应用 Dockefile 构建镜像时,将会把上下文目录的所有货色载入到镜像中。因而很多状况下,会间接将 Dockerfile 放在其所须要的上下文目录中。同时,这也意味着上下文目录(或者说 Dockerfile 目录)不应该有其余文件,否则将会节约额定的空间。如果不得不存在其余文件,能够应用.dockerignore
以相似.gitignore
的模式防止文件被导入至 Docker 中
为了方便使用,用户能够间接针对一个 URL 连贯进行构建。这个 URL 能够是一个 Git 仓库,也能够是一个 tar 压缩包。Docker 会主动拉取、下载对应内容,并将其作为构建上下文进行构建。如果传入-
,则会从 stdin 读入要编译的 Dockerfile 内容、
镜像历史
应用docker history <镜像名>
能够查看镜像的提交历史(这可能会裸露镜像历史中的命令,造成安全隐患)
镜像删除
对于不再应用的镜像,能够应用docker rmi [镜像名称/ID]
来删除镜像。删除镜像将会开释未被其余镜像应用的分层,同时会导致所有依赖该镜像的容器无奈间接运行。
容器
执行的镜像称为容器,能够了解为类与实例之间的区别。在任何状况下,都应该确保容器是无状态的——容器能够随便的敞开、删除、重启,而不会影响业务性能。
对于容器中须要保留的状态,应用存储卷来存储
要基于某个镜像运行容器,应用docker run [选项] 镜像名 [命令] [参数...]
。最常见的模式为docker run -it -p 80:80 -v ./data:/data xxxx /bin/bash
。
如果要启动的镜像不存在,将会主动调用pull
命令下载镜像。
应用docker help run
能够获取具体的解释,这里只介绍罕用的一些参数。
参数 | 解释 | 备注 |
---|---|---|
-d | 后盾运行 | 容器在后盾运行,所有输入将会输入至日志。能够应用docker container logs <容器名> 查看 |
-e | 环境变量 | 设置环境变量 |
--gpus | 应用 GPU | |
-i | 放弃 stdin 激活 | 程序将应用宿主的 stdin |
--name | 设置容器名称 | 默认会随机一个名字 |
-p | 映射的端口号 | 格局为-p <宿主机端口>:<容器端口> ,能够屡次传该参数映射多个端口 |
-P | 随机映射端口号 | 将容器内凋谢的端口全副映射到宿主机的随机端口 |
--read-only | 设置容器只读 | |
--rm | 容器完结后主动删除 | |
-t | 连贯到容器后应用的终端 | 须要绝对路径 |
-u | 应用指定用户 | |
-v | 挂载的存储卷 | 格局为-v <宿主机门路>:<容器绝对路径> ,能够屡次传该参数挂载多个存储卷(宿主机门路应用相对路径时,会基于存储卷目录) |
-w | 默认工作目录 |
容器状态
容器存在有运行、进行两种状态。对于已进行的容器,能够应用docker container start <容器名>
再次启动它。而对于正在运行中的容器,应用docker container stop <容器名>
终止。
对于用户应用-it
连贯的容器,当用户应用exit
或是 CTRL+D 退出后,会立刻终止。容器中没有正在运行的前台程序时,也会立刻终止。
能够应用docker ps
或docker container list
查看正在运行的容器状态,增加-a
则能够查看所有(包含已进行)的容器状态
进入容器
对于后盾运行的容器,能够应用docker attach
和docker exec
来进入容器。这两种的区别在于应用attach
进入后退出,将会导致容器进行;而docker exec
不会导致容器进行。
前者相似于间接挂入正在执行的前台程序,而后者更相似于 SSH 新建一个终端(能够应用-it
指定应用的终端)
容器导出
容器与镜像一样,也能够应用docker export
导出,不过其原理上是先将容器存储为镜像,再将镜像导出。因而应用import
导入后,失去的是镜像, 而非容器。
容器转换为镜像
对于无状态的容器,能够将其提交为镜像。应用 docker commit [选项] <容器名> [镜像名[:标签]]
能够将一个容器转换为镜像。与 Git 的 commit 相似,这实际上是一个提交,用户能够应用-m
填写提交信息,应用-a
填写用户名,应用-p
在提交时暂停容器。
这是一种较为简单的镜像建设计划,然而正如同前文 Dockerfile 局部强调的,这种操作会建设并不会理论须要的分层,因而并不是较为优雅的实现计划。
在转换为镜像前,能够应用docker diff <容器名>
查看容器的改变,来确定这是不是一个优雅的新镜像。
删除容器
应用docker container rm
能够删除处于终止状态的容器。而对于正在应用中的容器,则能够应用docker container rm -rf
强行删除(会在删除前先进行容器)
如果想要删除所有未运行的容器,能够应用docker container prune
存储卷(目录挂载)
在 Docker 中,存储卷(volume)或者说宿主机文件/目录挂载实际上是一个货色——将宿主机的特定文件夹/文件挂载到容器中,以不便容器外部读写。惟一的不同在于,目录挂载对应的宿主机目录往往是用户指定的,而存储卷寄存于 Docker 指定的非凡权限目录(可能在/var/lib/docker/volumes
)
因为后面提到容器应该是无状态的,因而所有长久化的数据应该被寄存在存储卷中,也即宿主机中。这很好了解,容器可能会被删除,甚至 Docker 都可能会被删除,然而起码宿主机自身的文件夹还是较为平安的。
存储卷中文件的状态将和容器外部完全一致。比方如果在容器外部应用非凡用户建设一个文件,那么宿主机中看到的也将是对应的用户的 UID(宿主机可能不存在该用户)。
空间治理
Docker 所占用的空间蕴含四局部:
- 镜像
- 容器
- 本地卷
- 缓存
应用下述命令能够查看 Docker 所占用的空间
docker system df -v
如果心愿对空间进行清理,能够
- 应用
docker container prune
能够革除所有终止的容器 - 应用
docker system prune
能够在上述根底上,革除未被应用的网络、悬空的镜像和缓存 - 应用
docker system prune -a
能够在上述根底上,革除所有未被应用的镜像和所有缓存 - 对于未被应用的存储卷,须要应用
docker volume prune
来革除
其余操作
服务端配置{#daemon_config}
Docker 的服务端的配置寄存在/etc/docker/daemon.json
中(须要严格遵守 JSON 格局撰写,如列表的最初一项不带逗号)。
然而,大概率在很多状况下,间接改变daemon.json
会导致 Docker 无奈启动。造成这个问题的起因是:官网认为,如果systemctl
启动项和daemon.json
有抵触,阐明用户配置不当,可能会造成意想不到的谬误,因而在抵触时会间接报错。
实践上这仿佛没什么故障,然而一般而言,systemctl
默认会携带一些参数(如监听的地址),而这些参数可能又是咱们会常常改变的,这么就会导致无奈启动的概率会十分大。
要解决该问题也很简略,只须要批改systemctl
启动参数即可。依照下面的链接,批改/etc/systemd/system/docker.service.d/override.conf
文件为
[Service]ExecStart=ExecStart=/usr/bin/dockerd
接着应用上面的代码重载配置并重启 docker 即可
sudo systemctl daemon-reloadsudo service docker start
在这之后,因为systemctl
未传递任何参数,因而无论daemon.json
有哪些配置,都不会产生抵触导致出错。
调用近程服务端
上文提到过,Docker 的服务端和客户端实际上是拆散的,因而这里次要讲一下如何在本地调用近程 Docker 服务。须要留神的是,只管后果上与应用 SSH 到服务端后应用服务端上的 Docker 客户端后果一样,然而依然在某些非凡状况下存在意义(见下文)
应用上述的服务端配置局部,容许从daemon.json
配置后。写入
{ "hosts": [ "unix:///var/run/docker.sock", "tcp://0.0.0.0:2375" ]}
这里配置两种连贯到 Docker 服务端的形式:
- 应用本地 Unix 域连贯
- 应用凋谢到公网
2375
端口的 TCP 连贯(如果是127.0.0.1
,则只容许本机拜访)
须要特地留神的是,如果凋谢了公网连贯,那么须要自行进行安全性防护。因为任何人都能够尝试连贯到该服务,甚至能够借助端口扫描工具扫到你的服务器存在凋谢的 docker 服务。这将造成 <span style="color:red;font-weight:bold">安全隐患</span>(存在主动扫描工具挂马)。因而倡议只在测试环境或局域网中凋谢近程连贯。
在这之后,即可在另一台电脑应用 IP 和端口进行近程连贯了。
镜像减速!
家喻户晓,因为网络起因,国内应用位于海内的官网源会十分慢。因而往往须要应用国内的镜像源。
在/etc/docker/daemon.json
内配置如下内容(Windows 能够间接在图形界面内配置),即可抉择应用百度、网易、腾讯的镜像。享受高速的下载
{ "registry-mirrors": [ "https://mirror.baidubce.com", "https://hub-mirror.c.163.com", "https://mirror.ccs.tencentyun.com" ]}
乏味的想法和测试
在 Docker 跑数据库?
依照上述思路以及 Docker 的一些数据库镜像。可能会有这样的想法:
将数据库在 Docker 中运行,长久化数据挂载到宿主机中。这样部署只须要做好数据库长久化文件即可
看上去仿佛没什么故障,然而具体执行起来可能存在一些问题。首先是数据库的重要性应该是高于程序的。程序挂了,重启即可,失落的状态无限。而数据库挂了,不仅仅会导致短时间所有程序无奈应用,还存在数据失落的隐患。当引入 Docker 这一额定因素后,Docker 自身故障也将会减少数据库故障的概率。而数据库的长久化也不是实时的,依然存在数据失落甚至损坏的可能性。
只管数据库也有隔离的需要,然而更好的方法是将其运行在独自的物理机上,这样还能够确保数据的平安。
也有人提出数据库将会被 IO 瓶颈限度,不过这更多应该是针对于同一个设施运行多个数据库 Docker。集体认为这实际上并不能作为一个理由。
如果用这里始终强调的内容来看,更实质的起因在于应用 Docker 跑数据库并不优雅——数据库是有状态的,即便挂载存储卷依然有状态。这其实更相似于个能够但没必要的状况,Docker 提供的劣势无限次要在于部署不便,这对于绝对较为确定的数据库(市面上罕用的数据库十分固定,绝对于程序运行环境的复杂度而言,约等于一键部署)并没有什么意义。与其减少其余危险,不如间接宿主机跑。然而,如果是为其余用户提供一个疾速部署的 Demo,那么应用 Docker 部署数据库还是极为优雅的。
Docker 容器在本地还是服务器执行?
要验证很容易,既然是两个设施,那么他们的公网 IP 必然是不同的。
咱们别离在本机和服务器获取公网 IP
很显著,前者(本机)是教育网 IP,而后者(服务器上的容器)是腾讯云 IP。那么该问题得以确定:容器在服务器执行
能够近似将其看作一个 SSH 连贯,咱们只是连贯到服务器上执行操作而已。
Docker 挂载的目录在本地还是服务器?
同上, 能够将/home
挂载到 Docker 容器中,依据挂载后的内容即可分辨到底挂载的是什么目录。
本地的用户名为 ohyee,而服务端的用户名为 ubuntu。那么很显著,这里实际上挂载的还是服务端的目录。
然而,这是存在例外的。 Docker 为 WSL 提供了特供版,在这个特供版里,Docker 挂载的将会是 WSL 内的目录,而非存在于 Windows 的服务端目录。
另外值得一提的是,Windows 中的 Docker 实际上是运行于虚拟机的,因而挂载/
目录实际上挂在然而 Hyper-V 的 Docker 虚拟机目录。如果须要挂载某些 Windows 特定文件夹,能够应用/c/Users/...
,当然也能够在 WSL 中应用/mnt/c/Users/...
参考资料
- docker容器与虚拟机有什么区别?
- 《Docker 从入门到实际》
- Docker 教程|菜鸟教程
- Docker Volume - 目录挂载以及文件共享
- 在docker容器中开数据库,是否适合? - 知乎