文章目录
- [1 WSL安装docker](#1 WSL安装docker)
-
- [1.1 开启Systemd支持(关键前置)](#1.1 开启Systemd支持(关键前置))
- [1.2 安装Docker Engine](#1.2 安装Docker Engine)
-
- [1.2.1 卸载旧版本(若有)并安装基础依赖](#1.2.1 卸载旧版本(若有)并安装基础依赖)
- [1.2.2 添加阿里云的Docker官方GPG密钥和软件源](#1.2.2 添加阿里云的Docker官方GPG密钥和软件源)
- [1.2.3 正式安装Docker](#1.2.3 正式安装Docker)
- [1.3 配置Docker镜像加速(必做)](#1.3 配置Docker镜像加速(必做))
- [1.4 免sudo使用与验证](#1.4 免sudo使用与验证)
- [1.5 验证安装](#1.5 验证安装)
- [2 制作镜像](#2 制作镜像)
-
- [2.1 requirements.txt](#2.1 requirements.txt)
- [2.2 Dockerfile](#2.2 Dockerfile)
- [2.3 创建镜像](#2.3 创建镜像)
- [2.4 运行容器](#2.4 运行容器)
- [2.5 启动失败排查](#2.5 启动失败排查)
- [3 连接宿主机mysql服务](#3 连接宿主机mysql服务)
-
- [3.1 获取Windows主机在WSL中的IP地址](#3.1 获取Windows主机在WSL中的IP地址)
- [3.2 mysql设置允许远程连接](#3.2 mysql设置允许远程连接)
- [3.3 创建一个连接账号](#3.3 创建一个连接账号)
- [4 服务器警告](#4 服务器警告)
-
- [4.1 原因分析](#4.1 原因分析)
- [4.2 解决方案](#4.2 解决方案)
-
- [4.2.1 requirements.txt](#4.2.1 requirements.txt)
- [4.2.2 Dockerfile](#4.2.2 Dockerfile)
- [4.3 运行容器](#4.3 运行容器)
要在WSL 的Ubuntu 22.04内部直接安装原生的Docker Engine(不依赖Windows上的Docker Desktop),就按照在标准Linux系统中安装的方式来操作。为了完美适配Ubuntu 22.04并获得最佳体验,请按照以下4个步骤执行:
1 WSL安装docker
1.1 开启Systemd支持(关键前置)
WSL默认不使用systemd管理服务,但为了让Docker像在普通Linux中一样自动运行和管理,强烈建议先开启它。
一、启动
在Ubuntu终端中输入以下命令:
bash
sudo vim /etc/wsl.conf
在文件中写入以下内容并保存退出:
bash
[boot]
systemd=true
保存后,退出Ubuntu终端。在Windows的PowerShell(管理员或普通均可)中执行wsl --shutdown彻底关闭WSL,然后重新打开你的Ubuntu 22.04终端。
二、验证
验证配置的 systemd 是否成功自动启动,可以通过以下三种方式进行检验:
方式一:在Ubuntu终端中执行以下命令,查看1号进程(PID 1)的名称:如果输出结果是systemd,就说明WSL已经成功使用systemd作为初始化系统。
bash
ps -p 1 -o comm=
方式二:状态验证命令
如果配置成功,终端会输出当前系统的详细状态信息(包含State: running、Units: 等),而不会报错。如果配置未生效,通常会提示System has not been booted with systemd as init system的错误。
bash
systemctl status

方式三:检查Docker是否随系统自启
由于开启systemd的最终目的是为了让Docker等服务能像标准Linux一样自动运行,你可以直接重启一下WSL来验证Docker 是否已经自动启动:
(1)在Windows PowerShell中输入wsl --shutdown彻底关闭WSL。
(2)重新打开你的Ubuntu终端。
(3)直接输入docker ps或sudo systemctl status docker。
如果Docker服务能正常响应且显示为active (running),就证明systemd不仅启动了,而且成功在后台自动拉起了Docker服务。
1.2 安装Docker Engine
为了在国内网络环境下保证下载速度和成功率,这里直接使用阿里云的镜像源进行安装。依次执行以下命令:
1.2.1 卸载旧版本(若有)并安装基础依赖
bash
sudo apt-get remove docker docker-engine docker.io containerd runc
sudo apt-get update
sudo apt-get install -y ca-certificates curl gnupg
1.2.2 添加阿里云的Docker官方GPG密钥和软件源
bash
sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://mirrors.aliyun.com/docker-ce/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
sudo chmod a+r /etc/apt/keyrings/docker.gpg
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://mirrors.aliyun.com/docker-ce/linux/ubuntu \
$(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
1.2.3 正式安装Docker
bash
sudo apt-get update
sudo apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
1.3 配置Docker镜像加速(必做)
为了防止后续拉取镜像(docker pull)时出现超时或连接重置,需要配置国内镜像源。
执行以下命令创建或修改Docker配置文件:
bash
sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": [
"https://docker.m.daocloud.io",
"https://dockerproxy.com",
"https://hub-mirror.c.163.com"
]
}
EOF
配置完成后,重启Docker服务使配置生效:
bash
sudo systemctl daemon-reload
sudo systemctl restart docker
1.4 免sudo使用与验证
默认情况下,执行docker命令需要加sudo。
为了方便日常使用,可以将当前用户加入docker组:
bash
sudo usermod -aG docker $USER
newgrp docker
1.5 验证安装
运行官方测试镜像来验证安装是否完全成功:
bash
docker run hello-world
如果终端中打印出了"Hello from Docker!"的欢迎语,就说明你的Docker已经在 Ubuntu 22.04中完美安装并正常运行了!

这段英文是 Docker 安装成功后自动运行的一个测试容器(hello-world)输出的欢迎信息。它其实是在告诉你:"恭喜,你的 Docker 已经安装成功,并且正在完美运行!"
为了让你更清楚地了解发生了什么,将这段内容拆解为以下几个核心含义:
1、核心结论:一切正常
第一行 This message shows that your installation appears to be working correctly. 是最关键的。
意思: 你的 Docker 环境已经配置好了,没有报错,可以正常使用。
2、发生了什么?(技术流程)
这段文字详细解释了Docker为了显示这条消息所做的4个步骤,这其实也是Docker工作的完整生命周期:
(1)客户端联系守护进程:你在终端输入的命令(Client)成功联系上了后台运行的 Docker服务(Daemon)。
(2)拉取镜像:Docker自动从官方仓库(Docker Hub)下载了一个叫hello-world的小文件包(Image)。
(3)创建容器:基于下载的文件包,启动了一个隔离的小环境(Container)来运行程序。
(4)输出结果:程序运行的结果(也就是你看到的这段话)被传回给你。
3、接下来能做什么?
网页最后还给出了建议,如果你觉得这个"你好世界"太简单,可以尝试运行更复杂的系统(比如直接运行一个Ubuntu系统):
建议命令: docker run -it ubuntu bash
意思: 这会下载一个完整的Ubuntu系统镜像,并让你进入其中操作,而不需要你重新安装一遍Ubuntu。
总结来说: 你不需要做任何操作,只需要庆祝安装成功即可!
2 制作镜像
2.1 requirements.txt
bash
requests
Flask
xgboost-cpu
pandas
numpy
sqlalchemy
apscheduler
scipy
concurrent-log-handler
flask-cors
flask-executor
func-timeout
python-dotenv
scikit-learn
nvidia_nccl_cu12是xgboost的依赖项,在安装过程中会自动安装。这是正常现象,因为XGBoost支持GPU加速,会依赖NVIDIA的NCCL库。
如果不需要GPU加速,使用CPU版本的xgboost即可,避免安装NVIDIA相关依赖:
2.2 Dockerfile
bash
FROM python:3.11-slim
WORKDIR /deploy
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY app.py .
COPY config/ ./config/
COPY services/ ./services/
COPY utils/ ./utils/
COPY models/ ./models/
EXPOSE 5000
CMD ["python", "app.py"]
2.3 创建镜像
bash
docker build -f Dockerfile -t ths .

2.4 运行容器
bash
# 运行容器(将配置文件和日志目录挂载出来)
docker run -d \
-p 5000:5000 \
-v "/mnt/d/ztest/application.properties:/deploy/application.properties" \
-v "/mnt/d/ztest/logs:/deploy/logs" \
--name ths \
ths:latest
在后台启动一个名为ths的容器,并将容器内的特定文件和日志目录映射到你当前的宿主机目录,同时开放了5000端口。
1、-id:这是-i和-d两个参数的组合简写。
(1)-i(interactive):以交互模式运行容器,保持标准输入打开。
(2)-d(detach):让容器在后台运行(守护进程模式),不会占用你当前的命令行终端。
2、-p 5000:5000:端口映射。
格式为宿主机端口:容器端口。这里将宿主机的5000端口映射到容器内部的 5000端口,这样你访问本机的5000端口就能连接到容器内的服务。
3、-v "pwd/application.properties:/deploy/application.properties":挂载单个配置文件。
-v 表示挂载数据卷。
pwd是一个命令,代表你当前执行这条指令的目录。
这条指令把你当前目录下的application.properties配置文件,直接映射(覆盖)到容器内部的/deploy/目录下。这样做的好处是,你在宿主机修改配置文件后,容器内的应用能直接读取到最新配置,无需重新打包镜像。
宿主机上的文件路径(必须是绝对路径)。
映射文件时,宿主机的文件必须预先存在 ,否则Docker会将其当作目录创建。
文件映射是实时同步的,宿主机修改后容器内会立即更新。
4、-v "pwd/logs:/deploy/logs":挂载日志目录。
将你当前目录下的logs文件夹,映射到容器内的/deploy/logs目录。这样容器运行产生的所有日志都会直接保存在你的宿主机上,即使容器被删除,日志也不会丢失(实现了数据持久化)。
5、--name ths:为这个容器指定一个自定义名称ths。如果不指定,Docker会自动随机生成一个名字,不方便后续管理。
6、ths:latest:指定要运行的镜像名称和标签。这里使用的是名为ths,标签为 latest(最新版)的镜像。
一个小建议:
在实际使用中,-i(交互模式)和 -d(后台运行)通常不需要同时使用。对于这种后台运行的服务类容器,直接使用 -d 即可。-i 一般配合 -t(即 -it)在需要进入容器终端进行调试时使用。
2.5 启动失败排查
1、如果你运行docker ps后,发现列表是空的,找不到你的ths容器,这说明容器启动后因为某种原因(比如配置文件错误、程序崩溃)立刻退出了。
此时,你可以运行以下命令来查看所有容器(包括已经停止的):
bash
docker ps -a
2、如果在这里看到了ths容器,且STATUS一栏显示的是Exited,说明它启动失败了。你可以通过以下命令查看它的报错日志,来定位具体原因:
bash
docker logs ths

3、进入容器后的调试与安装:
即可直接进入正在运行的ths容器内部:
bash
docker exec -it ths /bin/sh
若容器没有正常运行,那这种方式就不行了,需要换一种方法。
4、可以通过"覆盖启动命令"的方式,用同一个镜像启动一个"临时调试容器",进去排查好问题后,再回去修改你的Dockerfile。
这个方法的核心思路是:启动镜像时,不让它运行原本的程序,而是让它运行一个能一直挂起的命令(比如/bin/bash),这样容器就不会因为程序报错而立刻退出了。
bash
docker run -it --entrypoint /bin/bash ths:latest
(1)-it:以交互模式进入容器终端。
(2)--entrypoint /bin/bash:这是关键!它告诉Docker:"别管镜像里原本设定的启动命令是什么,直接给我运行bash终端"。
(3)ths:latest:你原本的镜像名。
3 连接宿主机mysql服务
bash
docker run -d \
-p 5000:5000 \
-v "/mnt/d/ztest/application.properties:/deploy/application.properties" \
-v "/mnt/d/ztest/logs:/deploy/logs" \
--name ths \
ths:latest

3.1 获取Windows主机在WSL中的IP地址
因为WSL本质上是一个独立的Linux 虚拟环境,它内部的127.0.0.1或localhost 指的是WSL自己,而不是你的Windows主机。因此,你需要获取Windows主机在WSL网络中的IP地址来进行连接。
方式一:
bash
ip route | grep default
或
grep "nameserver" /etc/resolv.conf

方式二:Windows主机输入 ipconfig,找到带有WSL后缀的部分:

3.2 mysql设置允许远程连接
bind-address=0.0.0.0
3.3 创建一个连接账号
bash
CREATE USER 'dev_user'@'%' IDENTIFIED BY 'dev_pass';
GRANT ALL PRIVILEGES ON *.* TO 'dev_user'@'%' IDENTIFIED BY 'dev_pass'WITH GRANT OPTION;
FLUSH PRIVILEGES;
4 服务器警告
This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.
这是一个非常经典的提示,不是报错,而是一个善意的警告。
它的意思是:"警告:这是一个开发服务器。请勿在生产部署中使用它。请改用生产环境的WSGI服务器。
4.1 原因分析
当你用Python(比如Flask或Django框架)写完代码,直接用python app.py或 flask run启动时,程序会自动调用框架自带的一个简易服务器。
(1)开发服务器:就像"测试车",它启动快、方便调试,但性能差、不安全,只能让你自己在本地测试用。
(2)生产服务器:就像"正式上路的量产车",性能强、能扛住高并发、安全性高,适合真正给外部用户访问。
4.2 解决方案
需要用一个专业的"生产级WSGI服务器"来代替框架自带的开发服务器。
最常用且简单的是Gunicorn。
用Gunicorn启动你的项目,假设你的主程序文件叫app.py,里面的Flask实例叫app,你可以用下面的命令来启动:
bash
gunicorn -w 4 -b 0.0.0.0:5000 app:app
-w 4:表示启动4个工作进程(根据服务器性能调整)。
-b 0.0.0.0:5000:表示绑定到5000端口。
app:app:前面的app是你的Python文件名,后面的app是你代码里的Flask实例名。
4.2.1 requirements.txt
bash
requests
Flask
xgboost-cpu
pandas
numpy
sqlalchemy
apscheduler
scipy
concurrent-log-handler
flask-cors
flask-executor
func-timeout
python-dotenv
scikit-learn
pymysql
gunicorn
4.2.2 Dockerfile
bash
FROM python:3.11-slim
WORKDIR /deploy
# 复制依赖文件并安装(确保你的 requirements.txt 里包含了 gunicorn)
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
# 复制项目代码和配置文件
COPY application.properties .
COPY app.py .
COPY config/ ./config/
COPY services/ ./services/
COPY utils/ ./utils/
COPY models/ ./models/
EXPOSE 5000
# 使用 Gunicorn 启动应用
# 假设你的 app.py 文件中,Flask/Django 等应用实例的名字叫 "app"
# 如果你的实例名不叫 app,请将最后的 app:app 替换为 你的文件名:实例名
CMD ["gunicorn", "--bind", "0.0.0.0:5000", "app:app"]
你想启动 4 个工作进程,修改如下:
bash
CMD ["gunicorn", "--bind", "0.0.0.0:5000", "-w", "4", "app:app"]
4.3 运行容器
bash
docker run -d \
-p 5000:5000 \
-v "/mnt/d/ztest/application.properties:/deploy/application.properties" \
-v "/mnt/d/ztest/logs:/deploy/logs" \
--name ths \
ths:latest