第一次用 Docker 把一个 Python 小脚本打包运行:从 Dockerfile 到端口映射
一、问题引入:本地能跑,换台机器就跑不起来
我写完第一个 Python 小服务时,在自己电脑上一运行就能打开页面。可把代码发给同事,对方却说启动报错、端口不对,依赖版本也不一样。问题往往不在代码本身,而在运行环境:不同电脑上的 Python 版本、依赖和端口都可能不同。Docker 就是把代码和运行环境装进同一个镜像,走到哪里都按同一份说明启动。
二、准备一个最简 Python HTTP 服务
新建文件夹 mini-http,写一个 app.py,只用标准库,不用装第三方包:
from http.server import BaseHTTPRequestHandler, HTTPServer
class Handler(BaseHTTPRequestHandler):
def do_GET(self):
body = "Hello from Docker!".encode("utf-8")
self.send_response(200)
self.send_header("Content-Type", "text/plain; charset=utf-8")
self.send_header("Content-Length", str(len(body)))
self.end_headers()
self.wfile.write(body)
if __name__ == "__main__":
HTTPServer(("0.0.0.0", 8000), Handler).serve_forever()
它监听 8000 端口,收到请求就返回一句问候。这里写 0.0.0.0 很关键:在容器里只监听 127.0.0.1 时,容器外常常访问不到。先本地运行 python app.py,打开 http://localhost:8000 能看到问候语,再继续打包。
三、编写 Dockerfile,并逐行解释
在同一目录新建无扩展名的 Dockerfile:
FROM python:3.12-slim
WORKDIR /app
COPY app.py .
EXPOSE 8000
CMD ["python", "app.py"]
FROM python:3.12-slim 是选择已装好 Python 3.12 的较小基础镜像。WORKDIR /app 把容器工作目录设为 /app。COPY app.py . 把本地脚本复制到该目录,点号就是当前目录。EXPOSE 8000 只是声明容器服务用 8000 端口,真正打通内外端口要靠运行时的 -p。CMD 是容器启动时默认执行的命令,即运行这个脚本。
四、构建镜像、运行容器与端口映射
docker build -t mini-http:1.0 .
docker run -d -p 8080:8000 --name mini-http mini-http:1.0
build 的 -t 是给镜像起名和打标签,最后的点号表示 Dockerfile 在当前目录。run 的 -d 是后台运行,--name 是给容器起名。最关键的是 -p 8080:8000:冒号左边是宿主机端口,右边是容器端口,访问本机 8080 时,请求会被转发到容器里的 8000。打开 http://localhost:8080 能看到问候语,说明映射成功。之后可用 docker ps 查看容器,docker logs mini-http 看日志,docker stop mini-http 停止容器。
五、两个常见报错及排查思路
一是端口占用。启动时提示端口已被占用,先用 docker ps 看看有没有旧容器还在运行,有就先停掉;也可以不动容器端口,只换宿主机端口,例如改成 -p 8081:8000,再访问 8081。二是镜像拉取很慢。第一次构建要下载基础镜像,网络不好时等待会比较长,先确认是在下载而不是卡死;经常遇到时,可在合规前提下配置可用的镜像加速地址,或先单独拉取基础镜像,不要反复取消重来。
六、小结
第一次打包 Python 脚本,记住一条主线就够了:本地跑通小服务,用 Dockerfile 描述运行环境,构建镜像,再用 -p 宿主机端口:容器端口 暴露服务。端口方向最容易记反,左边是自己电脑的端口,右边是容器里的端口。跑通这一步,再学挂载目录、环境变量和多阶段构建都会顺畅很多。
- 点赞
- 收藏
- 关注作者
评论(0)