如何在远程服务器上部署 Docker 容器

  • 使用 Docker Compose 和 SSH 或 GitHub Actions 可以简化将容器部署到远程服务器的过程,并使服务更新更加容易。
  • WSL 2、VS Code 和 Dev Containers 等工具允许在远程 Docker 环境中进行开发,从而获得接近本地的体验。
  • Plesk 和 Portainer 提供用于管理本地和远程 Docker 主机、Compose 堆栈、卷和镜像的 Web 界面。
  • 借助 VNC/noVNC 和 Caddy,可以在远程容器中运行图形应用程序,并通过浏览器安全地访问它们。

在远程服务器上部署 Docker 容器

在远程服务器上使用 Docker 容器 它已成为任何想要部署现代应用程序而又不想被依赖项、库版本以及经典的“在我机器上运行正常”问题所困扰的人的必备工具。然而,当我们从运行一个简单的应用程序过渡到复杂的应用程序时,就会发现问题所在。 docker run 从在 Linux 服务器上本地部署 Docker Compose、GitHub 共享、Plesk、Portainer 甚至可通过浏览器访问的图形应用程序,到构建一个复杂的系统,事情就变得有点复杂了。

如果你的目标是在远程服务器上部署 Docker 容器 (Ubuntu、Debian、带有 WSL 2 的 Windows、云服务器、Plesk 等)并以可维护、自动化和安全的方式进行操作,本指南将为您提供相当完整的旅程:从远程使用 Docker Compose 的基本操作,到使用 VS Code 的开发环境,从 Plesk 进行部署,使用 Portainer 进行管理,以及使用 noVNC 和 Caddy 远程执行图形应用程序。

基本概念:Docker容器和远程部署

Docker 是一个容器平台 它将应用程序及其所需的一切(库、依赖项、二进制文件、最小系统配置)打包在一起,使其在任何安装了 Docker 引擎的机器上都能以相同的方式运行。与虚拟机的主要区别在于,容器不包含完整的操作系统;相反,它共享宿主机内核,从而生成更轻量级的镜像并提升性能。

在远程服务器上部署 Docker 容器 通常情况下,你需要一台运行 Docker 的主机(例如云端的 Ubuntu 服务器),并可选地安装 Docker Compose,然后将代码或镜像发送到该主机运行。你可以手动通过 SSH 执行此操作,也可以使用 GitHub Actions 实现自动化,或者将其集成到 Plesk 等控制面板或 Portainer 等工具中。

你将遇到的主要现实场景 谈到“远程 Docker”,它包含三个方面:本地开发但容器运行在另一台机器上(或在 WSL 2 中运行)、后端/前端服务的自动化部署,以及生产环境容器的管理(监控、日志记录、重启、网络策略等)。技术本身并没有改变,改变的是编排方式。

除了传统的后端服务之外Docker 提供了一项鲜为人知但功能强大的功能:在远程容器中运行图形应用程序(例如电子邮件客户端、集成开发环境、分析工具等),并通过 WebSocket 使用 VNC 从浏览器访问它们。当你的电脑性能不足时,这是一种利用强大服务器的便捷方式。

从远程服务器上的 docker run 到 Docker Compose

在远程服务器上使用 Docker Compose

手动部署是一种相当常见的模式。 它包括在 GitHub 上创建一个代码仓库、一台安装了 Docker 的远程 Ubuntu 服务器,以及一个 CI/CD 工作流(例如 GitHub Actions),该工作流会在您向某个分支推送代码时执行以下操作。 development o main:

  • 通过 SSH 连接到远程服务器。
  • 停止并移除正在运行的容器。
  • 从 Docker Hub(或您的私有镜像仓库)下载新镜像。
  • Ejecutar docker run 对于每项服务。
  • 让 Nginx(或您使用的反向代理)将流量重定向到每个容器的端口。

当你切换到 Docker Compose 时 流程大大简化,因为您无需逐个管理容器,而是可以在一个统一的框架中定义整个技术栈(前端、后端、数据库、缓存等)。 docker-compose.yml及其网络、体积和环境因素。

使用 GitHub Actions 最简单(也相当常见)的做法 工作流程应执行以下操作 cd 到远程服务器上的项目目录(您的 docker-compose.yml)并执行如下命令:

  • docker compose pull 带来最新图片。
  • docker compose down 停止并移除旧容器(可选) --remove-orphans).
  • docker compose up -d --build 如果你直接从服务器构建镜像。

这种方法效果很好,而且相当稳健。只要你能很好地控制凭证、环境变量和卷,你就可以通过阻止 GitHub Actions 拥有对服务器的完全 root 访问权限、限制 SSH 密钥、使用专用用户,甚至将 Docker 作为带有证书的安全远程服务公开,而不是通过 SSH 运行所有内容来提高安全性。

没有比这更好的“神奇方法”了。 对于一个简单的环境:关键在于自动化和编写高质量的代码。 docker-compose.yml使用不可变的图像标签(例如,特定版本),并具有某种回滚机制(例如,保存先前版本的合成或图像)。

使用 Docker、WSL 2 和 VS Code 构建远程开发环境

使用 VS Code 和 WSL 2 进行远程 Docker 操作

在 Windows 系统上,使用 WSL 2 和 Docker 进行开发非常常见。适用于 Windows 的 Docker Desktop 提供了一个基于 WSL 2 的引擎,允许您从同一台机器运行 Linux 和 Windows 容器,同时使用 VS Code 编辑代码并在本地浏览器中进行测试。

使用 WSL 2 设置远程容器开发环境的典型工作流程 是以下内容:

  1. 安装 WSL 2 和 Linux 发行版(例如 Ubuntu)。
  2. 在 Windows 上安装 Docker Desktop,然后在“设置”>“常规”中启用“使用基于 WSL 2 的引擎”选项。
  3. 在“设置”>“资源”>“WSL 集成”中,您可以选择要让 Docker 运行的 WSL 发行版。
  4. 您可以使用以下命令检查安装情况 docker --version 并运行 docker run hello-world 在 WSL 发行版中。

在容器“内部”进行开发 而且,不要仅仅将 Docker 作为引擎;VS Code 也至关重要。借助 WSL、Dev Containers 和 Docker 扩展,您可以执行以下操作:

  • 直接在 VS Code 中打开托管在 WSL 中的项目文件夹。
  • 使用以下方式在“开发容器”(Dev Container)中重新打开该文件夹: Dockerfiledevcontainer.json 描述您的理想环境(Python 版本、Node 等)。
  • 在容器中运行时,通过 VS Code 调试应用程序。

一个非常常见的例子 它适用于 Django 或 Node.js 项目:在 WSL 中克隆存储库,然后打开文件夹 code .您选择一个开发容器定义(例如“Python 3”),VS Code 会构建镜像并启动容器及其所有依赖项。之后,即使您的主机系统是 Windows,您也可以运行、调试并验证代码是否能在 Linux 上运行。

当你的机器性能不太强时,这种方法也很有用。因为你可以使用 Docker 将部分负载转移到远程服务器,并通过 SSH 和开发容器使用 VS Code 连接到该服务器,其工作方式几乎与本地服务器一样,但依赖于服务器的资源。

使用 Docker 和 Docker Compose 在云服务器上部署应用程序

搭建一个带有 Docker 的云服务器,准备部署。 对于大多数服务提供商来说,速度非常快:您选择一个已经预装了 Docker 的系统镜像,等待几分钟,您的机器就可以接收容器了。

部署简单 Node.js 应用程序的典型模式 应该是这样的:

  1. 在本地计算机上创建 Node.js 项目(例如,使用 Express 的“Hello world”项目):项目文件夹,子目录 app, npm init安装依赖项(例如) express)和一个 index.js 它会在端口 3030 上建立一个服务器,并发送一条基本消息。
  2. 使用 Docker 将应用程序容器化 Dockerfile 定义基础图像(例如) node:12),该 WORKDIR复制应用程序文件,运行 npm install 并暴露内部端口。
  3. 添加一个 .dockerignore 为了避免写出类似这样的话 node_modules.
  4. 创建一个 泊坞窗,compose.yml 在项目根目录中,标明版本号(例如, 3.8)并定义主要服务,其 build端口映射(3030:3030)和命令(node index).

项目和合成文件准备就绪后即可。部署到远程服务器通常遵循以下流程:

  • 您通过 SSH 连接到服务器。
  • 您可以克隆存储库或上传文件(Git、SCP、rsync……)。
  • 你安装 泊坞窗,撰写 如果它还没有安装(在许多发行版中,你必须将其与 Docker 分开安装,例如从 GitHub 下载二进制文件并赋予其执行权限)。
  • 你执行 docker-compose up (o docker compose up (取决于版本)以便下载镜像、构建应用程序镜像并启动容器。

经常被忽视的一点是供应商的防火墙。如果您的服务监听 3030 端口,您需要在防火墙规则中打开该端口,或者创建一个特定的策略并将其与服务器关联。否则,即使容器运行正常,您也只会看到来自外部的“连接被拒绝”消息。

一旦运行正常,您就可以访问该应用程序了。 使用服务器的公共 IP 地址和暴露的端口(例如, https://IP_DEL_SERVIDOR:3030或者通过像 Nginx/Traefik 这样的反向代理将该端口隐藏起来,该反向代理监听 80/443 端口。

使用 Plesk 和 Docker 管理远程容器

如果您使用 Plesk 作为控制面板您还可以依靠其 Docker 扩展程序,通过 Web 界面直接管理服务器本身和远程 Docker 主机上的容器。

Plesk 支持在多种操作系统上使用 DockerCentOS 7、RHEL 7、Debian 10/11/12、各种版本的 Ubuntu(18.04、20.04、22.04、24.04)、AlmaLinux 8/9、Rocky Linux 8.x 和更新的 Virtuozzo 7。在 Windows 版 Plesk 中,Docker 不是在本地运行,而是在充当 Docker 主机的远程机器上运行。

需要注意一些重要的限制。:

  • 如果 Plesk 部署在 Docker 容器内,则无法使用 Docker 扩展。
  • 要使用远程 Docker 服务(即外部主机),您需要额外的许可证或特定软件包(主机包、增强包、开发包)。
  • 由 Plesk 管理的 Docker 容器本身并不“可迁移”,但您可以使用卷或快照备份它们使用的数据。

在 Plesk 界面中,您可以搜索图片。 镜像既存在于本地仓库(镜像已下载到主机)中,也存在于 Docker Hub 中。要启动容器,控制面板会引导您:

  1. 游览 Docker > 容器 > 运行容器.
  2. 找到所需的镜像,并在 Docker Hub 上查看其文档(如果适用)。
  3. (可选)选择特定的图像标签/版本。
  4. 配置容器参数(环境变量、端口、卷、内存、自动启动等),然后单击“运行”。

Plesk 还允许您管理高级设置 对于每个容器:重新分配端口(自动或手动),决定端口是否可从 Internet 访问或仅可从 localhost 访问,限制容器可使用的 RAM,定义卷(主机和容器中的路径),或根据需要添加尽可能多的环境变量。

关于远程编排方面Plesk 可以与“远程 Docker 服务”配合使用。这涉及到在远程主机上配置 Docker 守护进程(例如,使用……) /etc/docker/daemon.json 支持 TLS 和 TCP 套接字),生成证书 .pem 并将该主机注册到 Plesk 中 Docker > 环境 > 添加服务器然后您可以将该 Docker 节点标记为活动状态,并通过同一界面在不同的服务器之间切换。

从 Plesk 部署 Docker Compose 堆栈

如果您已经在使用 Docker Compose 构建基础架构,那么您可以考虑以下情况:您可能对使用 Plesk 处理从文件部署“堆栈”感兴趣。 docker-compose.yml.

在 Plesk 中部署 Compose 的工作流程 这其实很简单:

  1. 进入 Docker > 堆栈 > 添加堆栈.
  2. 为该技术栈指定一个项目名称。
  3. 选择“撰写文件”的来源:编辑器(粘贴内容)、从计算机上传文件,或选择域的 Web 空间中的现有文件。
  4. 确认配置并允许 Plesk 声明和创建已定义的容器。

建造过程中建造的一切都 相关的 Compose 文件存储在网站的主目录中,方便访问构建过程中生成的日志、中间工件或其他文件。

Plesk 还有助于管理本地图像:来自 Docker > 镜像 您可以筛选、查看不同的产品标签、查看已用空间,并删除过时的图片以释放磁盘空间。这对于空间有限的远程环境尤为重要。

如果您使用 Nginx 作为前端 Web 服务器Plesk 应用代理规则(例如,在 nginx.conf (从域名)将流量路由到您的 Docker 容器,即使在 NAT 环境下也是如此。这省去了您手动处理远程服务器上反向代理配置的麻烦。

使用 Portainer 管理远程容器

Portainer 是一个轻量级的 Web 界面 对于 Docker 而言,它极大地简化了那些不想使用命令行的人们的日常工作。它本身就是一个容器,可以管理本地主机或多个远程主机(甚至可以与 Portainer Agent 配合使用)。

使用 Docker 在服务器上安装 Portainer 通常情况下,你需要遵循以下基本步骤:

  • 为 Portainer 数据创建卷: docker volume create portainer_data.
  • 通过映射端口 8000 和 9000 来启动 Portainer 容器,挂载 Docker 套接字(/var/run/docker.sock)以及数据量: docker run -d -p 8000:8000 -p 9000:9000 --name=portainer --restart=always -v /var/run/docker.sock:/var/run/docker.sock -v portainer_data:/data portainer/portainer.

这将使 Portainer 监听服务器的 9000 端口。和往常一样,您需要在防火墙中打开端口,或者通过 HTTPS 反向代理将其暴露出来。首次通过浏览器访问时,Portainer 会提示您创建管理员用户,然后您可以选择管理本地 Docker 容器还是其他远程主机。

Portainer 控制面板非常直观。您将看到活动容器、它们的日志、资源消耗统计信息、Compose 堆栈、网络、卷等等。更重要的是,它允许您使用不同的参数重新创建容器、更新镜像、管理堆栈,并通过单一界面集中管理多个远程服务器。

在远程容器中运行图形应用程序,并通过浏览器访问它们。

当你的电脑资源耗尽时 但如果您需要使用大型图形应用程序(例如电子邮件客户端、IDE 或逆向工程工具),一个非常有趣的解决方案是在功能强大的服务器上的 Docker 容器中运行它们,并通过 Web 访问它们。

一份资料翔实的案例研究 其思路是将 Mozilla Thunderbird 封装在一个容器中,通过 TigerVNC/noVNC 暴露其图形界面,并使用 Caddy 进行安全访问。这个概念几乎可以应用于任何 Linux 图形用户界面应用程序。

此类图形容器的基本架构通常包括:

  • 一款轻量级的 VNC/X11 服务器(TigerVNC),可用作显示服务器。
  • 一个极简的窗口管理器(OpenBox),用于管理窗口。
  • 一种小型、易于使用的服务器类型 easy-novnc 它将 VNC 公开为 WebSocket,并生成一个 HTML 页面以供浏览器连接。
  • supervisord 或者类似地启动和监控容器内的所有进程。
  • 应用程序本身(Thunderbird、GIMP 等)配置为显示在远程显示器上(DISPLAY=:0).

实际上,需要建立一个工作目录。 (例如, ~/thunderbird它们被放置在哪里:

  • Un 管理员配置文件 它定义了要启动的程序:TigerVNC、easy-novnc、OpenBox 和主应用程序,并设置了优先级,以便图形服务器在应用程序之前启动。
  • Un 菜单文件 OpenBox 配置桌面菜单(主应用程序、终端、带有 htop 的进程监视器等)。
  • Un 多阶段 Dockerfile 第一阶段编译 easy-novnc 使用 Go 语言,第二步是在 Debian 系统上创建最终镜像,安装 openbox、tigervnc、supervisor、控制台工具、应用程序(示例中为 Thunderbird),复制二进制文件和配置文件,创建一个非 root 用户并定义一个持久数据卷。 /data.

容器的默认命令通常委托给 supervisord。像普通用户一样启动它 gosu调整数据卷的权限后,容器启动时,VNC、noVNC、窗口管理器和应用程序会自动启动,您只需要访问 easy-novnc 暴露的 HTTP 端口即可。

为了使其更强大、更便于互联网用户使用在前面放置一个像 Caddy 这样的 Web 服务器(也放在容器中)是个好主意,它可以作为图形应用程序的反向代理,添加基本身份验证(哈希用户名和密码),还可以选择公开 WebDAV 以访问文件。 /data 从您的本地计算机。

利用网络、卷和 Caddy 来协调解决方案。

为了保持这种部署方式的有序性。 通常的做法是创建自己的 Docker 网络和一个或多个数据卷:

  • 例如网络 thunderbird-net它将被所有相关容器共享。
  • 体积 thunderbird-data 它将包含图形应用程序的用户配置文件和持久数据。

图形应用程序的容器 你可以用类似这样的命令启动它:

  • 政策 --restart=always 这样它就能独立站立。
  • 体积组装 thunderbird-data:/data.
  • 网络连接 thunderbird-net.
  • 可识别名称(thunderbird-app(例如)Caddy 将用于反向代理。

在另一个目录(例如, ~/caddy)Caddy 的形象是构建出来的 包含必要的模块(例如 WebDAV 插件)和一个 Caddyfile 其定义如下:

  • 一台运行在 8080 端口上的服务器。
  • Un reverse_proxythunderbird-app:8080 (或者 noVNC 暴露的端口)。
  • 用于浏览文件的其他路径(/files)以及 WebDAV(/webdav),两者都服务于数据量的内容。
  • 一块 basicauth 它使用从环境变量中读取的用户名和哈希密码来保护所有路径。

创建 Caddy 容器时同一卷书被汇编在一起。 thunderbird-data:/data它连接到网络 thunderbird-net 并且其端口已发布(例如, -p 8080:8080在主机上。有了它,您只需在浏览器中访问即可。 http://IP_DEL_SERVIDOR:8080输入您的凭据并单击连接即可开始远程使用图形应用程序。

长期维护很简单当您需要更新时,您可以停止并删除容器,使用新版本重建镜像,然后重新启动它们。 docker run 保持数据量,以便用户的设置和文件保持不变。

包含所有这些组件(Docker Compose、Plesk、Portainer、VS Code、WSL 2、Caddy、noVNC……) 从简单的后端部署到封装在容器中并通过浏览器完美访问的远程桌面,一切皆有可能,利用比你的机器强大得多的服务器,并对网络、安全、存储和更新保持相当精细的控制。