Goland.2023 采用 Run Targets 在 Docker 中运行代码 (本地+远程)

发布时间:2024年01月21日

一、背景

现状

网上相关的文章很少有用JB家自带的Run Targets功能实现远程运行的,这个功能在2021版本就出来了,但官方的文档主要围绕Goland和Docker在同一台机器上的情况进行配置,故通过本文章记录一下踩坑过程。

关于Run targets

官网介绍如下

可以直接从 IntelliJ IDEA (Goland也一样) 在另一个环境(如云或 Docker 容器)中运行代码。

对于某些运行/调试配置,您可以直接从 IntelliJ IDEA 在另一个环境(如云或 Docker 容器)中运行代码。

为了在目标上运行代码,只需在通常用于本地运行的运行/调试配置中定义目标执行环境即可。完成此操作后,在目标上启动应用与在本地启动应用没有什么不同。

二、测试代码

main.go

package main

import (
	"fmt"
)

func main() {
	fmt.Println("Hello, World!")
}

go.mod

module targetTest

go 1.21

这里 Golang 1.21 采用 Go Modules 而不是 GOPATH
请自行测试是否能在本机运行,这里不再赘述

三、预备知识

  • 了解Docker的基本运行,容器、镜像、目录映射相关概念
  • 了解go build命令的使用,可以在本机上跑代码
  • 了解Go Modules,GOPATH已被淘汰
  • 了解如何通过ssh连接到服务器,并在服务器上安装docker
  • Docker Desktop(windows)是基于WSL2 (Windows Subsystem for Linux)

    Docker并没有办法直接读取Windows文件系统中的文件
    需要将文件映射到Linux系统(Docker
    宿主机)后,再映射到容器内部

四、操作

为了更方便理解,我们从windows docker开始

在同一台电脑上安装Goland和Docker Desktop
如果你只想在Linux上操作,可以读完本文后自行尝试

①Windows编写代码,在Windows Docker中运行

编写完代码后
添加Run/Debug Configuration
在这里插入图片描述
跟在平常本机Go运行一样,选择Go Build
在这里插入图片描述
与本机运行不同,这里我们选择Docker
在这里插入图片描述
如果安装了Docker Desktop(Windows),这里会直接识别
在这里插入图片描述
选择 Docker windows (即 Docker Desktop)
因为Docker和Goland在同一台机器,这里虚拟路径可以不用设置
在这里插入图片描述
回到上一级,设置image tag,这就是我们平常用的docker pull拉取
直接从网上拉golang的最新golang:latest镜像

如果要映射容器相关接口,可以在下面的Run options中使用-p 8080:8080
这里--entrypoint= --rm 代表在容器停止后删除它,方便我们多次调试

在这里插入图片描述
点击Next将开始拉取,如果慢可以进行docker换源,不再赘述
在这里插入图片描述
拉取完毕后点击Next,什么都不用动直接Create
经测试这里的 Project path on target 不影响我们后续配置
在这里插入图片描述
如果Docker和Goland在一台机器上,那么还是非常简单的
到这里基本就完成了,Configuration保持默认配置就行

注意 这里的 Package Path 应该是和你的go.mod第一行的module targetTest对应,不懂的可以去补习一下Go Modules,一般默认的就是对的
在这里插入图片描述
运行测试,正常输出
在这里插入图片描述
顺利跑通,但是大多数情况下我们的Docker和Goland不是在一台机器上,也不都是Windows系统,下面我们分析已有的容器来进行进一步学习。

到docker desktop中查看容器运行记录以及相关信息
以下命令和映射都是Goland自动创建的

  1. /usr/local/go/bin/go 是golang容器中的go主程序
  2. build -o xxx 在xxx目录下构建我们代码的可执行文件
  3. 执行

在这里插入图片描述

这里这个/tmp/4a3bb我们不用深究,是build的临时输出目录
我们只需要执行这个目录中build完的可执行go程序即可

但是有一个/tmp目录我们要注意
可以看见 Goland 创建了一个 Mounts
在这里插入图片描述
在这里插入图片描述
这个项目绑定到了我们 Docker 宿主机的“D盘”中
我们在这里可以看到
Goland 创建的 Mounts 并不是我们Windows下的项目目录
D:\Projects\Goland_Projects\targetTest
而是Linux样式的
/d/Projects/Goland_Projects/targetTest?

这是因为新Docker Desktop是基于WSL2的,可以直接访问到windows下的文件,这样就可以在Docker容器中编译Windows硬盘上的文件了。

②Windows编写代码,在远程Linux上运行(SSH)

在了解了Goland自动创建的相关配置和映射方式后,我们尝试在Targets中添加我们服务器上的docker
这里我采用SSH的方式直接连接到Linux服务器(Docker宿主机)
可以观察是否连接成功
在这里插入图片描述
与Docker Windows不同,这里可以配置一个映射目录。
本人在这里卡了很长时间,才发现:

这个映射目录并不是指的我们Docker容器中的目录
而是从本地(Goland)映射到Docker宿主机

重点来了,这里默认的路径映射需要修改为Linux对应风格的路径
这里的路径和WSL2(Docker Desktop)中是对应的

可以推断Goland在生成cmd的时候是默认根据WSL风格来进行的
如果不映射则会定位不到项目目录,后面详细介绍。

此时如果我们以默认参数运行,可能会出现以下错误
tmp/***/___go_build_targetTest__1_.exe: 未找到

在这里插入图片描述
出现这类错误,同时带有exe,这是因为Goland默认还是本地编译的。

值得一提的是,如果使用前面的Docker Windows在本机运行是不会出现错误的,因为WSL已经帮我们完成了路径映射

但是我们现在希望在远程容器Linux内编译并运行,需要加上这个勾
在这里插入图片描述
此外,你还可能碰到另一个错误,这与我们设置目录映射有关。
在这里插入图片描述
我们回去继续分析Goland启动的容器,可以发现
"WorkingDir": "/tmp/1f56aabb-e787-444b-8ad0-4e6751954c41"
指定了一个工作目录,也就是我们平常执行go build时所cd到的目录
继续查找可以发现,这个目录是绑定到我们Docker宿主机的"D盘"中
在这里插入图片描述
这个目录跟我们之前分析的项目目录是一样的。
所以,如果使用SSH远程调用服务器上的Docker进行build,一定要记得设置Docker选项卡中的目录映射

因为远程服务器并不像WSL一样会帮我们自动映射。
直接在WorkingDir中go guild,会找不到源代码,所以编译不成功

再次检查SSH/Docker的目录映射
在这里插入图片描述

总结

这里其实完成了两次映射,在使用WSL时,第一次映射自动完成。

  • Goland项目目录: D:\Projects\Goland_Projects\targetTest
  • Docker宿主机目录: /d/Projects/Goland_Projects/targetTest?
  • 容器内工作目录:/tmp/xxxxxxx

至此,我们才能完成go build。
在这里插入图片描述
Run Target的在自动配置Docker时没有将自动生成的配置暴露出来,这导致当Docker运行在本机上时运行非常完美,但一旦迁移到远程Docker时,会存在一些不透明的错误。

这与我们在前面提到的,Docker无法读取Windows文件系统下的文件有关
JetBrains的IDE提供了一个将Windows文件映射到Linux的table
在这里插入图片描述
远程(SSH)情况下会有所不同,图中的

  • 蓝色Host 为我们运行Goland的Windows电脑
  • 红色Linux virtual machine 为我们的远程服务器(Docker宿主机)
  • 绿色Docker Engine 为我们常用的Docker引擎

本文通过分析Run Target自动拉取并生成命令的容器进行分析,探究了Docker容器的自动部署原理。

本文仅作学习记录
JB起初这么设计肯定有他的道理,可能只是为了解决Windows运行Docker的问题。
在实际生产中,我们可以使用dockerfile进行容器自定义配置
或者在本机Docker上测试完毕后再打包迁移到其他平台

如果你在Linux环境下开发(运行Goland)则没有这些问题

This table is not available on a Linux host, where Docker runs natively and you can mount any directory to the container.

文章来源:https://blog.csdn.net/qq_23211951/article/details/135731353
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。