资讯详情

VS Code 配置 Docker 开发环境:从 Remote-Containers 到 Dockerfile 实战指南

📅 2026/10/19 10:31:52 | 华诺云谱 👁 阅读
VS Code 配置 Docker 开发环境:从 Remote-Containers 到 Dockerfile 实战指南
很多人在学 Docker 的时候第一个想法都是“这玩意儿到底能干嘛”。我当初也一样光看文档里那些镜像、容器、仓库之类的概念知道是什么但始终找不到一个能让自己沉浸进去的切入点。后来我试着把每天写代码用的 VS Code 搬进 Docker 里顺着这个方向一步步折腾反而把 Volumes、端口映射、Dockerfile、环境隔离这些曾经绕来绕去的知识点全都串起来了。这篇就记录一下我这次实践的完整过程也把配置环境时踩过的坑一并写出来。如果是刚接触 Docker 的朋友这篇文章可以帮你找到一个具体的学习场景不用对着抽象的概念发呆。如果你已经能在本地用 VS Code但还不太理解容器开发是怎么回事那你也会在这篇里看到一套能直接跑通的配置方法。1. 整体思路与方案选型1.1 核心需求解析这个标题拆开看其实只有两件事在 Docker 中打开 VS Code并且配置好环境。但“配置环境”这四个字背后藏着很多决定怎么做的基础判断。以我自学初期的理解想在容器里用 VS Code大概有几条路可以走。第一条是直接在容器里装一个完整的 VS Code里面带桌面或者走 Web 模式通过浏览器访问。第二条是在自己的电脑上安装 VS Code再通过远程开发插件连接进容器。第三条是绕过 docker exec 之类的命令用共享文件的方式在宿主机里编辑代码、在容器里跑命令。我最终选的是第二套方案也就是 Remote - Containers 体系。不是因为它最炫酷而是因为它是普通人最容易理解和控制的。你只需要在 VS Code 里装一个扩展然后告诉它“帮我这个文件夹跑在一个新的容器环境里”剩下的连接、插件安装、端口映射VS Code 会帮你妥善安排。整个过程很直观也很有学习的价值。第一套方案本身没问题但把整个 VS Code 塞进容器里需要额外处理图形界面或者 Web 访问这对刚接触 Docker 的人来说会多一层无关的复杂度。第三套则更像传统开发模式对容器本身的知识帮助不大。我这次用的技术栈比较常规Docker Desktop 作为容器运行时VS Code 作为宿主机上的编辑器配合 Remote - Containers 插件来管理远程容器。整套方案跨平台表现也比较稳定Windows 和 macOS 上体验几乎一致。1.2 为什么选择 Remote - Containers关于方案选型我个人的体会是学习新技术时最难的不是学不会而是“反馈太慢”。如果你用命令行去管理容器敲一堆指令之后输出一堆日志但你代码该放哪、环境变量该设多少、依赖装在哪个层里全靠脑补那很快就退坑了。Remote - Containers 的核心优势在于它把容器从“一个需要 SSH 进去的黑盒子”变成了“一个存在于你左侧文件树里的文件夹”。你可以在 VS Code 里直接打开容器内的目录写代码、装扩展、开终端体验和本地开发几乎没有区别。这种“没有区别”非常重要因为它能让你把自己已有的编程习惯平移到容器里把注意力空出来专门理解容器相关的概念。而且它天然支持 Dev Container 的配置方式。你可以用一份devcontainer.json来定义当前项目要来什么镜像、装哪些工具、映射哪个端口、挂载哪个目录。这比手动 docker run 一遍遍试要舒服得多因为你把环境定义写成了文件它变成一个可复现的结果。正是这种可复现性让我下定决心用这个方案。因为我的目标不只是把这个项目跑起来我还要搞清楚这套环境配置到底是怎么工作的。如果哪天环境坏了我还能靠这份配置文件把它找回来。2. 环境准备与前置条件2.1 宿主机上的必备工具先准备环境。我用的宿主机系统是 Windows 11当然macOS 和主流 Linux 发行版的操作基本一致后面我会把有差异的地方单独指出来。第一件要装的是 Docker。Windows 上强烈建议装 Docker Desktop安装过程不需要特别处理但装完一定要把 WSL 2 准备好。现在新版 Docker Desktop 安装时基本会帮你完成 WSL 2 的启用但如果你电脑的虚拟化功能没开或者系统里没启用“适用于 Linux 的 Windows 子系统”这个 Windows 功能安装后 Docker 可能启动失败。检查 Docker 是否正常工作的最快方式是打开终端执行docker --version docker run hello-world如果docker run hello-world能正常输出一段说明文字说明 Docker 引擎已经跑起来了。我第一次跑这行命令的时候看到那条 “Hello from Docker!” 的时候真的有种自己已经开始掌控容器的错觉虽然后来才发现这只是第一道门。第二件要装的是 VS Code。这个没什么好说的直接官网下载稳定版就行。唯一提醒一点如果你用 Remote - Containers 方案千万别把 VS Code 装到 Docker 内部它只是连接工具跑在宿主机上就好。然后是 VS Code 里需要安装的扩展列表这里直接列出来Remote - ContainersDocker 扩展其中 Remote - Containers 是核心Docker 扩展用来在 VS Code 侧边栏管理镜像和容器非常直观建议直接配套安装。除了这些还需要装一个 Git。因为 devcontainer.json 在后面的流程中会配合 Dev Container 的功能使用并且很多示例工程都是直接通过 Git 仓库拉取的没有 Git 会卡在第一步。装完之后打开 VS Code在扩展市场里搜“Remote Development”会看到一个三方扩展包里面包含了 Remote - SSH、Remote - Containers、WSL 等一整套远端开发工具。如果不想单独手动装直接装这个扩展包也行。2.2 Docker 基础概念速览既然标题是“个人自学 docker”我默认读到这里的人不一定要对 Docker 有特别深刻的理解所以先把后面会用到的几个概念用大白话说一遍这能省掉后面看配置文件的困惑。镜像也就是 Image你可以把它想象成一个压缩好的“打包好的操作系统环境”它里面可能有 Ubuntu 系统、Node.js、Python也可能是你配好的某个数据库。它本身是不运行的只是一个静止的模板。容器则是镜像运行起来之后的实例换句话说Dockerfile 定义了镜像长什么样容器则是你真正在里面敲命令的那个“现场”。卷也就是 Volume它的作用是把宿主机上的某个目录和容器里的某个目录关联起来。这样你在宿主机里改代码容器里立刻能看到。因为默认情况下容器里生成的数据在容器删除后就没了但挂在卷里的数据会留在宿主机上这份持久化能力很重要。端口映射就是把容器内部某个端口和宿主机上的某个端口对应起来。比如容器里跑了一个开发服务器监听 3000 端口你可以通过映射让宿主机访问 3000 端口时流量自动进入容器。我建议你在正式操作之前先自己亲手跑一下docker run -it --rm ubuntu:22.04 bash这句命令会拉取一个 Ubuntu 22.04 的镜像并直接进入容器内部的 bash。玩一会儿看看里面是 Linux 的样子没有鼠标没有桌面环境然后再输入 exit 退出。这个体验会让你对后面所有概念都有更痛的记忆点。3. 核心实操从零搭一个容器开发环境3.1 创建项目目录与基础配置这次我不拿别人的 Demo 做示范而是从头新建一个项目。假设我们要用一个简单的 Python 开发环境来做演示顺便验证容器里的环境是不是真的可用。先在宿主机的某个位置创建项目目录名称我取为docker-vscode-demo并在里面创建两个文件。第一个是devcontainer.json第二个是Dockerfile。目录结构先立好docker-vscode-demo/ ├── .devcontainer/ │ ├── devcontainer.json │ └── Dockerfile └── app/把这个目录用 VS Code 打开。这一步要特别注意不要直接随便打开而是要以根目录的方式打开项目文件夹因为 VS Code 的 Remote - Containers 工作原理是基于打开的文件夹来创建容器的。如果你以单个文件的方式打开或者层级选错了后面进入容器后看到的路径和你预期会有偏差这种偏差会让人一开始死抓头皮。打开后按F1输入 “Remote-Containers: Add Development Container Configuration Files”选择这个命令VS Code 会询问你基础镜像类型。我们这里手动写配置文件更可控所以直接跳过向导自己动手。3.2 Dockerfile 的编写与原理先看这份 Dockerfile我尽量一行行把思路写清楚FROM python:3.11-slim RUN apt-get update apt-get install -y --no-install-recommends \ git \ curl \ build-essential \ rm -rf /var/lib/apt/lists/* WORKDIR /workspace CMD [bash]第一行FROM python:3.11-slim指定了基础镜像。为什么选slim版本因为完整版的 Python 镜像中带了大量文档、缓存、静态库等东西体积大、构建慢。虽然容器能塞下但没必要。slim 版本裁剪掉了很多东西只保留了跑 Python 的基础这符合我们做环境配置的主线目标也为后面学习镜像精简做铺垫。第二行是安装一些基础工具。git是必备的因为后面大多数项目都要从 Git 仓库里拉代码。curl用来调试网络请求build-essential里包含 gcc、g 等编译工具如果在容器里需要编译 Python 的 C 扩展没有它就会报错。这行命令里我把安装包和清理缓存的步骤用连起来目的是让最终镜像里不残留 apt 的索引缓存这样镜像更小、也更干净。WORKDIR把容器里的工作目录切换到/workspace。这个目录名是约定俗成的VS Code 的 Remote - Containers 默认会把项目挂载到容器内的/workspace下。你在宿主机上看到的项目根目录进入容器后看到的位置就是这个目录。最后一句CMD [bash]设置容器启动后默认执行的命令打开一个 bash。这不是最必需的但是当你要调试容器的时候它能防止容器启动后立刻退出给你一个手动进入的入口。这里有个小细节一开始我不知道slim里连ping都没有后来在容器里想测试网络才发现命令不存在。这件事是我第一次感觉到容器和虚拟机真正的区别——虚拟机里东西相对完整而容器里的东西非常精简缺什么你自己装就完了。3.3 devcontainer.json 的配置细节写完 Dockerfile还差 devcontainer.json 把 Dockerfile 和我们这个 VS Code 工作区关联起来。这份配置我一开始也是抄网上的模板后来才逐渐理解每个字段的作用。先给出我实际使用的完整版本{ name: python-dev-container, build: { dockerfile: Dockerfile }, workspaceFolder: /workspace, mounts: [ source${localWorkspaceFolder},target/workspace,typebind,consistencycached ], customizations: { vscode: { extensions: [ ms-python.python, ms-python.vscode-pylance ], settings: { python.defaultInterpreterPath: /usr/local/bin/python } } }, runArgs: [ --name, python-dev-demo, -e, MY_ENV_VARhello_from_container ], remoteUser: root }逐一说一下。name只是显示在 VS Code 底部的名字可以随便起但最好有意义。比如我起了 python-dev-container看到就知道这个容器跟 Python 开发有关。build指定构建方式。dockerfile: Dockerfile表示要用当前.devcontainer文件夹下的 Dockerfile 来构建一个镜像。这个字段也可以换成image: python:3.11-slim那样的话就不自己写 Dockerfile直接用一个现成的镜像更省事但灵活性低。workspaceFolder是容器内 VS Code 默认打开的目录跟 Dockerfile 里的 WORKDIR 保持一致都是/workspace。mounts这行是我最初觉得最难懂的。它的作用是把宿主机上的当前项目目录直接挂载到容器的/workspace目录。${localWorkspaceFolder}是 VS Code 提供的变量会自动替换成你在宿主机打开的那个项目根目录。这样你改宿主机里的代码容器内立刻能看到不需要手动同步。customizations里的vscode.extensions就是容器启动后 VS Code 会自动安装的插件列表。很多人容易漏掉这一步结果进入容器后发现 Python 插件没有语法高亮、智能提示全都没有。这里把 Python 和 Pylance 放进去进入容器后 VS Code 会自动装好这两个插件。settings里设置了 Python 解释器的路径。这里我写了/usr/local/bin/python。如果不确定这个路径可以在终端里进入容器手动执行which python查看。也可以不写让 VS Code 自动检测但自动检测有时会误判成别的位置所以我干脆显式指定尽管多一行但稳。runArgs是给 docker run 传额外参数的地方。--name给容器固定一个名字后面管理它的时候不用记那一长串容器 ID好认多了。-e则用来设置环境变量这里只是做个示范实际用的时候你可以传入数据库的连接串、业务配置等。remoteUser设置 VS Code 进入容器后的默认用户。我写成 root 主要是为了演示方便因为改系统文件、装东西时不用反复切换权限。自己用可以正经团队开发的时候还是建一个普通用户更安全。配置到这里按F1输入 “Remote-Containers: Reopen in Container”VS Code 会开始构建镜像第一次构建可能需要几分钟取决于网络和镜像大小。如果顺利的话你会看到 VS Code 右下角提示连接成功左下角显示当前容器的名字表示你已经在容器里面了。这时你在终端里执行pwd python --version如果分别输出/workspace和Python 3.11.x说明容器环境已经成功跑起来了。3.4 验证环境是否按预期工作光看 Python 版本还不够为了确认这真的是一个干净的环境我建议跑一个小脚本测试。在项目根目录的app文件夹里放一个main.py内容简单一点import sys print(Hello from container!) print(Python version:, sys.version) try: import requests print(requests module exists) except ImportError: print(requests module not found, need to install)故意用了一个需要第三方包的写法。因为 Python 基础镜像默认不会包含 requests 这个库运行这个脚本时你会看到 “requests module not found” 的提示。这时你可以用 pip 在容器环境里安装依赖pip install requests再跑一次脚本就能看到成功的输出。这一步的意义在于让你直观理解容器环境是独立的宿主机上的 Python 没有装 requests容器里通过 pip 安装后它只在容器内生效不会污染宿主机。而如果你把容器删了再重建一个这个环境又会回到初始状态。这种“说了算”的掌控感是整个容器学习过程中最值得体会的部分。4. 配置环境的常见问题与排查真正动手做的时候很少有人能一把过。我折腾这段时间攒下了一些高频问题和对应的排查思路列出来供大家参考。4.1 容器一直处于构建中或反复失败这个情况优先级最高我先说。第一次构建时如果卡了很久大部分原因不是配置错了而是镜像拉取太慢。境内用户下载 Docker Hub 镜像时经常遇到类似问题这是由网络环境导致的需要自行想办法解决网络连通性。我个人的经验是先确认 Docker 是否真的在拉镜像在终端里执行 docker pull python:3.11-slim 试试单独拉取这个镜像看它表现如何。如果单独拉也特别慢说明问题在网络侧和配置文件无关。等镜像拉完再回到 VS Code 里 “Prebuilding” 或者 Rebuild Container这时候构建过程会明显加快因为本地已经有基础镜像的缓存了。Troubleshoot 时还有个常用的操作打开 Docker Desktop 的 Dashboard找到相关容器或镜像看它们的日志。VS Code 里显示的构建日志有时被折叠了但 Docker 自己的日志是比较全的。4.2 进入容器后项目目录为空或路径不对这个问题非常常见。你在宿主机上明明看到app文件夹存在但进入容器后 ls /workspace 却是空的或者里面根本不是你的项目文件。出现这种情况八成是 mounts 配置写错了或者打开文件夹的层级选错了。比如你在 VS Code 里打开的是docker-vscode-demo的上层目录那么${localWorkspaceFolder}就会指向那个上层目录挂载进去的东西自然不是你期望的。解决办法很简单重新在 VS Code 里以项目根目录打开一次然后重建容器。顺带提醒一句每次改完 devcontainer.json 里的 mounts 或 Dockerfile记得执行 “Rebuild Container”而不是直接 “Reopen in Container”因为重建会让配置变更真正生效。4.3 容器内没有语法高亮和智能提示进入到了容器但 VS Code 里写代码却“光秃秃”的没有语法高亮也没有智能提示。不用怀疑就是插件没有安装到容器内。需要区分一点你在宿主机上安装的 VS Code 插件默认不会自动跑到容器里除非它本身支持远程开发。所以我们在 devcontainer.json 里写 extensions 字段就是为了让容器创建时自动装好这些插件。如果你没定义这个字段或者刚开始不知道字段名写错了可以在容器内按CtrlShiftX手动搜索并安装插件。这种方式会直接装进容器的 VS Code Server 里也能让环境立刻好起来但缺点是这一切无法通过配置重现。所以建议最终还是要写进 devcontainer.json。还有一个点Python 解释器路径如果写错会在右下角弹出一个提示说“Select Python Interpreter”你手动选择容器内的那个路径即可不必死磕配置文件先让开发环境跑通更重要。4.4 端口映射不生效或访问不到等项目里跑起了一个 Web 服务之后你可能会想在宿主机浏览器里访问它。这时候如果发现访问不了先查 devcontainer.json 里有没有写forwardPorts: [3000]。这个字段的作用是告诉 VS Code 把容器里的 3000 端口转发到宿主机。它不是必须的因为 VS Code 有时能自动检测端口并提示你转发但显式配置更可靠。如果你用的是 runArgs 手动做了-p端口映射那跑测试的时候确保主机端口没被占用。Windows 上常见的坑是 Hyper-V 保留了部分端口段随机分配的端口可能冲突换个端口号可能就正常了。4.5 Dockerfile 中 apt 源慢或安装失败我前文提到过用 apt-get 来装 git 和 build-essential。如果你在容器里执行 apt 相关命令时发现超级慢那是软件源的问题可以考虑换用国内镜像源。做法是先在 Dockerfile 里写RUN sed -i s|deb.debian.org|mirrors.aliyun.com|g /etc/apt/sources.list然后把 apt-get update 放到这行后面。但这里我要强调一下不要盲目照抄这行不同 Debian 版本源文件的位置和格式会不一样有些是.sources格式不是.list格式。改之前先进入容器里查看文件内容再针对性替换。4.6 容器删了重来会不会丢数据会丢。如果不做任何持久化处理容器被删除后容器内部文件系统里的一切改动都会丢失只有挂载到宿主机上的部分能留下来。所以如果你在容器里手工装了某个依赖但这个依赖没有写进 Dockerfile那么你一旦销毁重建容器那个依赖就不存在了。这是容器设计上的核心身份要求我们“用代码描述环境而不是靠手工进入容器修修补补”。写进 Dockerfile 的东西每次构建都会自动重现。这也是为什么我建议你在初学阶段所有“额外装的东西”都必须想办法落到配置里。就算现在只是临时测试也要养成习惯记下来这样在别人看来你才是真正掌握了这门工具。5. 进阶扩展让容器开发更顺手当你已经把上面这套配置跑通对容器的基本工作流有了概念之后可以在这个基础上再加一点实用的东西这也算是我在自学过程中的一次主动升级。5.1 把常用工具注入 Dockerfile我后来给自己的环境里加了 zsh 和 oh-my-zsh原因是默认的 bash 提示符不够直观没有显示 git 分支等信息看久了总觉得别扭。在 Dockerfile 里添加RUN apt-get install -y zsh \ sh -c $(curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh) --unattended安装完成后修改 devcontainer.json把remoteUser对应的默认 shell 改掉或者通过customizations里的 settings 把terminal.integrated.defaultProfile.linux设为 zsh。说实话这个步骤对学习 Docker 本身帮助不大但对提升日常开发体验非常明显。每次打开容器终端看到友好的提示符我的积极性都会保持在一个不错的状态。5.2 使用预构建镜像如果你不希望每次创建新项目都经历一遍“构建镜像”的过程可以把装好常用工具的环境打成镜像并推到镜像仓库。具体做法是在本地的 Dockerfile 目录下执行docker build -t my-dev-image:latest . docker login docker tag my-dev-image:latest your-registry/my-dev-image:latest docker push your-registry/my-dev-image:latest然后在项目的 devcontainer.json 里把build部分换成{ image: your-registry/my-dev-image:latest }这样就不需要本地构建了每次创建环境直接拉取现成镜像即可。这特别适合团队场景统一环境版本效率会高很多。我还在自学过程中发现Docker 官方提供了一个丰富的镜像仓库里面预置了很多开发环境的镜像比如 python、node、openjdk 等。有时候不用自己从头写 Dockerfile直接选一个官方镜像搭配合适的 devcontainer.json 就够了。5.3 多容器协同脱离单容器局限VS Code 的 Remote - Containers 其实支持多容器场景。也就是在一个工作区里跑一个“Dev Container”作为主开发环境然后通过 Docker Compose 把数据库、Redis 等依赖服务跑起来形成一个完整的小型开发体系。这对学习 Docker 来说是一个更好的跳板。你需要理解 compose 文件里的 services、depends_on、ports 等概念而这些概念比单个容器更能体现容器化开发的真实组合玩法。我当时为了模拟一个 Web 应用在项目里加了一个docker-compose.yml里面放了 app 服务和 db 服务。然后在devcontainer.json里把dockerComposeFile指向这个文件VS Code 会直接以 Compose 的方式启动整个环境。这样做的性价比非常高因为在同一台机器上你能同时体会到文件挂载、环境变量传递、服务依赖顺序、日志输出等概念一次全部打通。6. 环境配置之外的一点体会说实话最初我在网上看到别人把开发环境写进 Docker 里总觉得多此一举明明自己电脑上什么都有何必绕一圈。等自己真的用容器开发了两周之后才开始理解它的真正优势环境的可重复性、项目间的隔离性、以及不用再担心“我的电脑能跑你的电脑跑不了”这种问题。在配置过程中我经历的最挫败的一件事是容器启动后无法访问目录里的文件。我反复检查配置文件最后发现是挂载路径写错了。那一刻我反而很开心因为故障让我记住了 mounts 的格式。故障是最好的学习引擎这件事在容器学习里体现得淋漓尽致。另外我建议手里有一定基础的朋友可以主动把某个自己的旧项目改造成容器的开发方式。从零开始写 Dockerfile由简到繁地补依赖以这种“重构”的方式学习理解深度会远超单一教程的跟练。如果你只是想快速体验一下容器里的 IDE 体验按本文操作从新建目录、写 Dockerfile、配置 devcontainer.json 到进入容器跑代码总共也就半小时。但如果你是像我一样想借这个场景真正学懂 Docker我希望你能在跑通之后停下来多问问自己几个为什么为什么挂载这么写为什么安装包要放在同一层为什么容器要设置名字这些问题的答案才是你真正学到的东西。
📝

华诺云谱内容团队

资深建站顾问 · 行业研究员

10年+企业数字化服务经验,专注智能建站、SEO优化与品牌营销,持续输出建站技巧、行业洞察与营销干货,已帮助5000+企业实现数字化增长。

你可能需要的服务

订阅华诺云谱资讯周报

每周一封,精选建站技巧、SEO与营销干货,直达邮箱。已有 8,000+ 企业主订阅,助你少走弯路。

↑