前言
本系列所有关于 Docker 的笔记仅针对 Docker Desktop for Windows 实践。
下载并安装 Docker Desktop for Windows。根据官网提供的信息,Docker Desktop for Windows 仅能在 Windows 10 专业版或企业版上运行,实践表明,教育版 Win10 也能支持,理论上家庭版也能使用,因为新的 Docker 可以使用 WSL 2 引擎,而 WSL 2 支持 Win10 家庭版。有成功运行的同学可以文末留言。
Get Started with Docker | Docker
Docker Desktop for Windows user manual | Docker Documentation
Docker 是一个沙盒性的容器应用引擎,我们将应用程序以及相关的依赖环境打包到容器中,后续就可以简洁快速地进行镜像移植,只要能运行 Docker 的系统就能拉取我们打包的镜像,从而创建容器,而我们的应用程序则运行在该容器中。Docker 就是一个虚拟机,我们打包好的容器是一个虚拟机实例,做到了一次部署处处运行,而与传统的虚拟机相比,Docker 采用了操作系统内核共享机制,显然更省资源。
对我来说,Docker 可以减少在不同机器上部署同一个应用的机械重复工作量,不用每次都要手动安装复杂的环境依赖,即实现了安装运维的自动化。比如对于部分需要使用 SQL Server 的项目,每次在客户机器上从头安装 SQL Server 都是一个繁琐的过程,使用 Docker 则只要几个命令就能安装成功。有的项目也可以 push 到 Docker hub 仓库中,为客户部署时 pull 到本地安装即可。这就是我接触 Docker 的初衷。慢学 Docker 系列将记录这个过程的零碎笔记。
更快的 WSL 2 引擎
WSL 2(Windows Subsystem for Linux 2)是适用于 Linux 的 Windows 子系统,是在 Windows 上的轻量级虚拟机上运行的完整 Linux 内核,从此我们就可以在 Win10 上快速运行 Linux 命令和工具啦。
Docker for Windows 支持基于 WSL 2 或 Hyper -V 的引擎。基于 WSL 2 的 Docker 可以直接利用 Linux 工作区,无须额外维护 Windows 构建脚本,其动态内存分配功能也能够改善资源分配问题,表现在如果你勾选了 WSL 2 引擎,就不用手动为 Docker 分配 CPU 和内存了,Docker 将仅仅使用所需的最优 CPU 和内存资源。
安装好的 Docker 要想使用基于 WSL 2 的引擎而非基于 Hyper-V 的引擎,则要求 Windows 安装 WSL 2 Linux 内核,若未安装会在 Docker 启动时会提醒,根据提示安装即可。
Win10 上安装完 WSL 2 后建议为 Docker 启用基于 WSL 2 的引擎,即勾选 “Settings-General-Use the WSL 2 based engine” 选项。Docker 安装完一般是默认勾选的,可以自己确认一下。
勾选了 WSL 2 系统会自动为 Docker 分配 CPU 内存,而且 Windows 会与容器共享所有文件。同时 Docker 拉取安装的镜像将由 WSL 2 管理,如果需要迁移镜像位置或备份镜像数据,需要通过 wsl 命令进行。
如果勾选 WSL 2 后 Docker 启动失败,可以到 Windows 控制面板的 “启用或关闭 Windows 功能” 中关闭 Hyper-V 功能后重启 Docker。关于该问题可以参考:
先列出已安装的 WSL 发行版及其版本。
可以看到 Docker 为我们安装了 docker-desktop 和 docker-desktop-data 两个发行版,版本是 2,即 WSL 2,其中我们关注的是 docker-desktop-data 发行版,是用于运行 docker images 即镜像,同时存储镜像数据。该发行版默认将数据(运行数据与镜像文件)存储于 C 盘,位置为%LOCALAPPDATA%/Docker/wsl/data/ext4.vhdx,随着镜像数据增加,将占据更多 C 盘空间,这点需要额外注意。如果空间不足,可以迁移位置,迁移命令的搜索关键词为 “wsl –export docker-desktop-data”,可自行查找。
对 WSL 2 CPU 或内存自动分配有疑问或需要手动分配,可以查阅管理 Linux 分发版 | Microsoft Docs
更换镜像源
国内网络用户安装完 Docker 后建议更换下镜像源的地址,否则拉取镜像的速度可能会慢得令人发指。
镜像加速地址
截至目前(2020-10)可用性较高的是 阿里云容器镜像加速 和 DaoCloud 的 Docker 镜像站 。阿里云需要登录后才能获取镜像加速地址,不想注册的可以使用我的地址:https://7mvpvz9f.mirror.aliyuncs.com。DaoCloud 直接访问镜像站获取地址即可。个人使用下来感觉阿里云的加速效果更胜一筹。
配置镜像加速
在系统右下角右键 Docker 菜单,选择 Settings,在设置中选择 Docker Engine 配置项,在编辑窗口中填写加速地址:
{
"registry-mirrors": ["https://7mvpvz9f.mirror.aliyuncs.com"]
}
编辑完成后点击 Apply & Restart,等待 Docker 重启后新的镜像地址即可生效。
Docker 在 Win10 上有 Linux containers 和 Windows containers 两种运行模式,二者取其一,在其中一种模式上安装的镜像无法在另一个模式中使用,除非有特殊需求,否则为获得最佳的文件系统性能,一般使用 Linux containers 模式。
实例-Docker 部署 SQL Server 镜像
本节将通过创建一个 SQL Server 容器,演示 Docker 部署一个镜像的常用操作。
拉取 SQL Server 镜像
SQL Server 只有 2017 及以上版本支持以容器运行
以下命令拉取最新版本的 SQL Server 镜像:
docker pull mcr.microsoft.com/mssql/server
也可以拉取特定版本的镜像:
2017-latest
docker pull mcr.microsoft.com/mssql/server:2017-latest2019-latest
docker pull mcr.microsoft.com/mssql/server:2019-latest
创建 SQL Server 容器
建议通过命令行运行 SQL Server 镜像,从而创建一个容器,通过 Docker for Windows 客户端运行镜像创建 sqlserver 容器的功能有 bug,会导致创建的容器运行不起来。
docker run -e "ACCEPT_EULA=Y" -e "SA_PASSWORD=844e#6a3d73" \
-p 1433:1433 --name la-sqlserver -h sqlserver \
--env LC_ALL=C.UTF-8 \
-d mcr.microsoft.com/mssql/server
这里的命令基于我们前面拉取的 mcr.microsoft.com/mssql/server 镜像创建一个名为 la-sqlserver 的 SQLServer 容器。其中 –env 参数为容器指定系统编码,这样才支持 Unicode 显示。
运行的同时必须设置 sa 密码,否则 SQL Server 无法成功启动。要求的密码策略为:长度至少 8 位,必须同时包含字母、数字和特殊符号。
下表对前一个 docker run
示例中的参数进行说明:
参数 | 说明 |
---|---|
-e “ACCEPT_EULA=Y” | 将 ACCEPT_EULA 变量设置为任意值,以确认接受最终用户许可协议。 SQL Server 映像的必需设置。 |
-e “SA_PASSWORD=<YourStrong@Passw0rd\>” | 指定 SQL Server 的 sa 密码 |
-p 1433:1433 | 将主机环境中的 TCP 端口(第一个值)映射到容器中的 TCP 端口(第二个值)。 在此示例中,SQL Server 侦听容器中的 TCP 1433,并对主机上的端口 1433 公开。 |
–name sqlserver | 为容器指定一个自定义名称,而不是使用随机生成的名称。 如果运行多个容器,则无法重复使用相同的名称。 |
-h sqlserver | 用于显式设置容器主机名,如果不指定它,则默认为容器 ID,该 ID 是随机生成的系统 GUID。 |
mcr.microsoft.com/mssql/server | 指定 SQL Server 镜像。 |
运行命令无报错后通过 docker ps -a 可以列出已经运行的容器。
连接到 SQL Server
更多关于 SQL Server 容器连接参考 Microsoft Docs:部署并连接到 SQL Server Docker 容器 – SQL Server | Microsoft Docs
成功创建运行容器后可以在 Docker 客户端查看容器状态。
这里我使用 SSMS 工具从容器外连接 SQL Server,连接成功后就可以按照 SQL Server 的普通操作对容器 SQL Server 进行操作。
附加 SQL Server 数据库文件
由于启用了 WSL 2,我们可以直接把数据库文件从 Windows 主机复制到容器内,之后就可以执行附加命令。
1、将文件复制到容器中
命令格式为:docker cp <Host path> <Container Name/ID>:<Container path>,其中容器 name 或容器 ID 可以通过 docker ps --no-trunc
命令查询得到,注意查询容器 ID 的话不要使用 docker ps -a 命令,该命令查询显示的容器 ID 不是完整的。
将宿主机 E:\program_data\mssql\data 下的 lahotel.mdf 文件和 lahotel.ldf 文件复制到容器内的/var/opt/mssql/data 目录下,在宿主机执行命令如下:
docker cp /E/program_data/mssql/data/lahotel.mdf la-sqlserver:/var/opt/mssql/data
docker cp /E/program_data/mssql/data/lahotel.ldf la-sqlserver:/var/opt/mssql/data
命令中的 la-sqlserver 是我们前面创建的 SQL Server 容器的名字,可以通过 docker ps -a 命令查询到。
2、执行复制命令后我们登陆到容器中查看是否有复制成功
在宿主机执行命令如下,以 root 身份登录容器:
winpty docker exec -ti --user root la-sqlserver bash
进入容器后执行命令查看目录下是否存在前面复制过来的文件
cd /var/opt/mssql/data
ls
注意以上是要进入容器内执行的命令。
3、为复制的文件授予写权限
文件复制到文件后只有读权限,在执行数据库附加命令时将报错,需要给.mdf 和.ldf 文件授予写权限。以 root 身份进入 la-sqlserver 容器(见步骤 2),执行以下命令:
chmod 777 /var/opt/mssql/data/lahotel.mdf
chmod 777 /var/opt/mssql/data/lahotel.ldf
4、附加数据库
使用 SSMS 连接容器中的 SQL Server,新建查询执行 SQL 命令,附加我们的 lahotel 数据库文件:
EXEC sp_attach_db @dbname = 'lahotel',
@filename1 = '/var/opt/mssql/data/lahotel.mdf',
@filename2 = '/var/opt/mssql/data/lahotel.ldf'
以上 4 个步骤的命令执行结果如下述 A、B 截图。
A、复制文件到容器内并授予写权限:
B、SQL Server 数据库附加结果:
5、从容器复制(备份)文件
对于容器内的数据库文件 mdf 来说,当容器删除之后数据也随之丢失,有时候需要手动备份数据到宿主机中,最原始的备份方法是从容器中将数据复制出来。
5.1 可以直接从容器内复制整个目录:
docker cp la-sqlserver:/var/opt/mssql/data /E/program_data/mssql/data/backup
docker cp la-sqlserver:/var/opt/mssql/data /E/program_data/mssql/data/backup
以上命令将 la-sqlserver 容器的/var/opt/mssql/data 目录复制到宿主机的 E:\program_data\mssql\data\backup 文件夹
5.2 也可以复制指定文件
docker cp la-sqlserver:/var/opt/mssql/data/lahotel.ldf /E/program_data/mssql/data/backup/
docker cp la-sqlserver:/var/opt/mssql/data/lahotel.mdf /E/program_data/mssql/data/backup/
以上命令将 la-sqlserver 容器内的 lahotel.mdf 和 lahotel.ldf 文件复制到宿主机的 backup 文件夹内。
话外:Docker 数据保留
在保留数据方面,除了手动复制备份外,Dcoker 推荐的方法是使用数据卷绑定挂载(bind mount)或数据卷容器(Volume)的方案。前者是在主机上将目录作为容器中的数据卷装载,后者是使用一个容器共享的数据卷,指定容器的某个目录数据持久化到数据卷中,且数据卷的内容独立于容器的声明周期之外,除非手动删除卷。这样就可以在不同容器间共享数据卷,在新容器指定数据卷,从而达到数据持久化。
关于两种数据管理方法的区别:
1、bing mount 方法更为简单,设置后将在主机上的 Docker 的存储目录中创建一个新目录,并且由 Docker 管理该目录的内容,但是其依赖于具有特定目录结构可用的主机文件系统,在不同宿主机(相同系统)或不同系统之间兼容性较低。/2、
2、Volume 方法更为灵活,兼容性最高,也是 Docker 首先推荐的方法。相比 bind mount 方法,数据备份或迁移更方便,可以在不同容器之间共享数据,删除容器后卷的数据仍然留存。
更多的 Docker 数据管理参考以下文档: