docker-18-WSL中安装docker并部署flask服务

文章目录

  • [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
相关推荐
少年白char1 小时前
整理上万首音乐后的完整工作流:下载、刮削、播放与避坑指南
docker·nas·musictag·音乐刮削·音乐标签
凯瑟琳.奥古斯特4 小时前
SQLAlchemy核心功能解析
开发语言·python·flask
木雷坞7 小时前
K8s GPU 推理服务 ImagePullBackOff 排查与预热
云原生·容器·kubernetes·gpu算力
萧行之9 小时前
Docker部署Loki+Grafana+Vector实现全服务器日志监控(含N8N/SSH/Fail2ban监控)
服务器·docker·grafana
人工智能培训9 小时前
工程科研中的AI应用:结构力学分析技巧
人工智能·深度学习·机器学习·docker·容器
计算机安禾10 小时前
【Linux从入门到精通】第35篇:容器化技术预备——Docker安装与基本概念
linux·运维·docker
子木HAPPY阳VIP10 小时前
信创UOS,Docker 完整操作部署(Dockerfile部署方式)&排错整合
linux·运维·redis·nginx·docker·容器·tomcat
AOwhisky10 小时前
Kubernetes调度与服务暴露:从“定时任务”到“服务发现”的完全指南
linux·运维·云原生·容器·kubernetes·服务发现
Leinwin11 小时前
Claude 四月宕机七次:从一次事故看企业级 AI 部署的容灾设计
后端·python·flask