目录
一. Docker 是什么
1. 背景
在聊 Docker 是什么之前,我们先来回顾一下传统的产品开发上线涉及到的难点。一款产品从开发到上线,经历了开发环境、测试环境、生产环境等不同的操作系统、运行环境和应用配置等环境。在项目管理中,还涉及到不同版本以及不同版本之间兼容性等问题。
这些问题对开发人员和运维人员都是极大的考验,同时对各方的协作也有一定的要求。不然就会出现 ”代码在我这里运行的好好的啊“,这种尴尬的局面。而 Docker 的出现就是提供了一套用来解决此类问题的标准解决方案。—— Java烟雨
Docker 的口号是 ”一次创建或配置,可以在任意地方正常运行“。如口号所说,Docker 的出现对于开发和运维人员是一大福音,基于 Docker 可以方便地搞定标准化的发布流程,再也不用纠结不同环境导致的问题了。
Docker 的使用可以理解为软件是带环境安装的,即安装的时候把原始环境一模一样的复制过来一份。这样也就消除了不同机器运行结果不同的问题。Docker 本质是一个开源的应用容器引擎,基于 Go 语言,并遵从 Apache2.0 协议开源。它可以让开发者打包应用以及依赖包到一个轻量级、可移植的容器中,然后发布到任何流行的 Linux 机器上,也可以实现虚拟化,可用于开发应用、交付应用、运行应用等场景。
2. 相关概念
Docker 的架构如图所示,主要由镜像(image)、容器(container)和仓库(repository)构成:
2.1 镜像
Docker 中的镜像是一个只读的模板,是文件与 meta data 的集合。它可以看作是一个特殊的文件系统,除了提供容器运行时所需的程序、库、资源、配置等文件外,还包含了一些为运行时准备的一些配置参数(如匿名卷、环境变量、用户等)。
镜像是基于分层的实现的,每一层都可以添加删除文件,从而形成新的镜像。镜像可以理解为是一个树状结构,每一个镜像都会依赖于另一个镜像。镜像可以用来创建 Docker 容器,一个镜像可以创建多个容器。
2.2 容器
容器是用镜像创建的运行实例,是在 image 的最后一层上面再添加一层。容器的定义和镜像几乎一模一样,也是一堆层的统一视角,唯一区别在于容器的最上面那一层是 可读可写 的。当我们把容器与镜像作对比时,可以看到镜像负责存储和分发,容器则负责运行。容器可以被启动、开始、停止、删除,并且每个容器都是相互隔离的、保证安全的平台。可以把容器看做是一个简易版的 Linux 环境和运行在其中的应用程序。
2.3 仓库
仓库是集中存放镜像文件的场所,它有点类似于 Maven/Git 的仓库,当我们需要镜像文件时,可以从远程仓库中拉取。仓库和仓库注册服务器(Registry)是有区别的。仓库注册服务器上存放着多个仓库,每个仓库中包含了多个镜像,每个镜像有不同的标签(tag)。
3. Docker 的优点
在没有使用 Docker 时,如果开发完毕一个项目,需要打包成 war 或者 jar 包。然后在服务器上进行各种环境的安装、配置以及应用程序维护,比如:JDK、Tomcat、数据库等。而且,上述的配置在开发环境、测试服务器、生产服务器(通常会有很多个),都需要进行一遍同样的操作,工作量相当繁重。在使用了 Docker 之后,我们可以自己创建一个空的镜像从头构建,也可以使用公共仓库中已经构建好的镜像,直接使用。当需要在不同环境中进行部署时,直接使用构建好的镜像即可,一次构建,多环境多次使用,方便快捷:
总的来说,Docker 具有以下优势:
- 更高效地利用系统资源;
- 更快的启动时间;
- 一致的运行环境;
- 持续交付和部署;
- 更轻松迁移;
- 更轻松的维护和拓展;
4. Docker VS 虚拟机
Docker 容器与虚拟机很相似,但它们之间又有着很大的区别。
虚拟机是通过软件模拟的具有完整硬件系统功能的、运行在一个完全隔离环境中的完整计算机系统。创建虚拟机时,会将实体机的部分硬盘和内存容量作为虚拟机的硬盘和内存,每个虚拟机都有独立的硬盘和操作系统,可以像使用实体机一样对虚拟机进行操作。因此,虚拟机会消耗大量系统资源和开销,尤其是当多个虚拟机在同一物理服务器上运行时,每个虚拟机都有自己的子操作系统,大量精力以及资源被用于虚拟化的部署和运行上。
Docker 容器虽然功能上类似于虚拟机,但容器并不是完整的操作系统,通常只包含必要的操作系统包和应用程序,这就是它们轻量级的原因。在一个机器上,十几个甚至几十个容器共享一个操作系统核心,占用资源少,启动速度快。并且容器都完全使用沙箱机制,相互之间不会有任何接口,保证了系统的安全性和稳定性。Docker 允许用户将基础设施中的应用单独分割出来,形成更小的部分容器,从而提高软件交付速度。
由此可以看出,传统的虚拟机是在宿主机之上,又添加了一个新的操作系统,这就导致了虚拟机的臃肿,不适合迁移。而 Docker 是直接寄存在宿主机上,避免了大部分虚拟机带来的困扰。Docker 是一个黑盒的进程,区别于传统的进程,Docker 可以独立出一个自己的空间,不会使得在 Docker 中的行为以及变量溢出到宿主机上。
容器与虚拟机的各项对比如下:
二. 环境检查
-
Ctrl+Shift+Esc 打开任务管理器确保 CPU 的虚拟化已启用:
-
打开:控制面板->程序->程序和功能->启用或关闭 Windows 功能,打开 “适用于 Linux 的 Windows 子系统” 和 “虚拟机平台”:
点击 “确定” 后等待搜索完命令后需要 重启;
三. 安装 WSL + Ubuntu
-
搜索 Windows PowerShell,用管理员权限打开,执行
wsl --install
指令下载 wsl:
-
在 Microsoft Store 中下载 Ubuntu 22.04.2 LTS,这种方法比 Windows PowerShell 中安装更快,还可以省去 wsl 装 Ubuntu 后需要 20.04 转 22.04 的操作;
-
下载完 Ubuntu 后直接打开会出现问题,需要先下载内核:https://aka.ms/wsl2kernel,下载完成后双击安装即可。Ubuntu 22.04.3 LTS 已经修复该问题,但默认内核是 WSL1,下载内核后可以使用
wsl --set-version Ubuntu-22.04 2
指令转换内核。wsl -l -v
指令可以用来查看内核版本:
-
安装好内核后再打开 Ubuntu,可以设置用户名和密码:
Ubuntu 22.04.2 LTS 中只接受 包含小写字母、数字和特定字符 的 UNIX 用户名,不然就会报错:
后续输入密码时请切换成 英文输入法,否则会出错! -
设置密码后,WSL + Ubuntu 安装完成:
-
由于 Ubuntu 中经常用到 CMake 工具,顺手装上:
# 添加 Kitware APT 仓库到系统中方便地获取 CMake wget -O - https://apt.kitware.com/keys/kitware-archive-latest.asc 2>/dev/null | sudo apt-key add - sudo apt-add-repository 'deb https://apt.kitware.com/ubuntu/ jammy main' # 更新软件包列表 sudo apt update # 安装最新的 CMake 版本 sudo apt install cmake # 安装成功后可以查看 CMake 版本号 cmake --version
注意,第二条指令中的
jammy
是 Ubuntu 22.04 的版本代号,其他版本的代号可以使用指令lsb_release -cs
得到; -
以及 python:
# 更新系统软件包 sudo apt update sudo apt upgrade # 安装 python3 sudo apt install python3 # 安装成功后可以查看 python 版本号 python3
四. 安装 Docker
-
在 VS Code 的扩展中安装 WSL,安装成功后在远程资源管理器中选择 Ubuntu-22.04 连接到 WSL:
连接到 WSL 后可以看到这是运行在 Ubuntu 上的; -
在 WSL 终端使用
sudo apt-get install apt-transport-https ca-certificates curl gnupg2 software-properties-common
指令安装 Ubuntu 常用的软件包和依赖项。安装时需要输入密码,切记要 切换成英文输入法,否则密码错误!如果密码忘记了可以参考 windows系统下的ubuntu子系统(WSL)忘记密码的解决方案; -
使用
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
指令在 Ubuntu 系统上添加 Docker 的官方 GPG 密钥;使用echo \ "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://mirrors.tuna.tsinghua.edu.cn/docker-ce/linux/ubuntu \ $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
指令向 /etc/apt/sources.list.d/docker.list 文件中写入 Docker 软件源的配置; -
更新软件包:
sudo apt-get update
; -
安装 Docker:
sudo apt-get install docker-ce
或者sudo apt install docker.io
;
至此 Docker 安装完成,可以使用docker version
指令验证 Docker 是否已正确安装并能正常工作。但为了能够在 Linux 中不通过 root 用户(sudo)就能直接访问 Docker,以及在运行于用户权限的 VSCode 中直接使用 Docker,还需要配置 Docker 组的用户权限; -
配置 Docker 的用户组权:
sudo usermod -aG docker $USER
,newgrp docker
,然后 重启电脑,否则后面将无法执行 docker 的指令; -
在 VS Code 中安装 Docker 和 Dev Container 扩展,然后关闭全部 VS Code 窗口;
-
打开 Windows PowerShell 切换操作系统至 Ubuntu 界面:
-
输入
newgrp docker
,code
,可自行打开 VS Code 窗口:
-
连接 WSL,查看 Docker 状态:
发现 Docker 没有自动打开,需要手动关闭后再打开; -
Windows PowerShell 中输入
wsl --shutdown
,然后关闭所有命令行,并重新加载 Ubuntu 上的 VS Code 窗口; -
在 Ubuntu 上的 VS Code 终端输入
sudo service docker start
,docker ps
后发现 Docker Daemon 没有启动。如果出现 ‘docker: unrecognized service’ 的报错,请重启电脑。如果出现 ‘Cannot connect to the Docker daemon at unix:/var/run/docker.sock. Is the docker daemon running?’ 的报错,执行systemctl start docker
启动 Docker; -
执行以下命令:
sudo apt install iptables sudo update-alternatives --set iptables /usr/sbin/iptables-legacy sudo update-alternatives --set ip6tables /usr/sbin/ip6tables-legacy sudo service docker start
如上图则表示 Docker 启动成功!
五. Docker 的使用
1. 基础命令
- 启动 Docker:
systemctl start docker
; - 关闭 Docker:
systemctl stop docker
; - 重启 Docker:
systemctl restart docker
; - 设置自启动:
systemctl enable docker
; - 查看运行状态:
systemctl status docker
; - 查看版本号:
docker version
;
Linux 系统中常使用
systemctl
或service
命令管理服务:systemctl
是基于 systemd 的,适用于基于 systemd 的现代 Linux 发行版;而service
是基于 SysVinit 的,适用于较旧的基于 SysVinit 的 Linux 发行版。如果执行systemctl
命令时遇到 ‘System has not been booted with systemd as init system (PID 1). Can’t operate.’ 报错,参考 Cannot connect to the Docker daemon at unix:/var/run/docker.sock. Is the docker daemon running?。
2. 镜像命令
- 拉取镜像:
docker pull 镜像名[:tag]
(tag 为版本号); - 运行镜像:
docker run 镜像名
; - 删除镜像:
docker rmi -f 镜像名/镜像ID
;
3. 容器命令
- 运行容器:
docker start 容器ID
; - 停止容器:
docker stop 容器ID
; - 删除容器:
docker rm -f 容器ID
; - 展示容器列表:
docker ps -a
;
更多 Docker 指令可参考 docker 常用命令大全。