前言

省流:为了让编译这一步在本地机器上运行。

在使用 Goland 编写并部署 Go 代码时,有的项目我采用 docker-compose 的形式将代码打包进镜像编译运行。

Server 选择的是运行这个 docker-compose 脚本的机器,Build:Always 是为了每次都从代码编译一次镜像,这样做虽然可以一键编译部署到远程服务器,但顺序一般是 ①上传代码文件(上下文) -> ②运行 Dockerfile 编译镜像 -> ③运行 docker-compose 重建容器并运行。

这样做在理论上是没问题的,但平时总能遇到比如服务器性能较差编译时间长、编译时容器停止、网络断线导致编译中断等一系列问题。

思路

由于 IDEA 系 IDE 的配置都自带 “Before Launch” 功能,可以设置当前配置运行之前要运行的配置,形成一个工具链。

这样可以有一下两种思路:

  1. 将 docker-compose.yml 中的 build: . 改为 image: some_image ,并在运行在本地编译镜像且 push 到某个 registry 上。

  2. 将 docker-compose.yml 中的 build: . 改为 image: some_image ,在运行在本地编译镜像且直接将镜像复制到远程服务器上。

如何直接复制

第一种思路主要在于如何找到或部署一个符合自己保密要求的 registry,这里分享一下如何实现第二种。

其实在装了 Docker 插件的 Goland 中有直接将本地镜像复制到远程服务器的方法。

不过它没法整合到运行配置里,也就是不能自动化,但 bash 脚本可以,如下指令的效果是一样的。

docker save alpine | bzip2 | ssh root@your.server docker load

运行结束后,终端会提示"Loaded image alpine",这时就说明成功了,可以看看远程服务器上是否有这个最新镜像。

这个指令可以打包压缩上传并加载到远程服务器,但每次都要输入 ssh 密码,可以采用密钥登录或 sshpass 的方式。

docker save alpine | bzip2 | sshpass -p password ssh root@your.server docker load

这是 Linux 指令,那么在 Windows 平台如何运行呢?一般的指令在前面加 wsl 即可传递给 wsl 来执行,不过这里是带竖线的管道指令,需要将它作为一个整体传递给 wsl,否则会提示如“找不到bzip2”之类的报错。

这个 ISSUE中有关于 wsl + 管道的讨论。

wsl bash -c "docker save alpine | bzip2 | sshpass -p password ssh root@your.server docker load"

将它保存为“docker_copy_image.ps1”文件,并创建一个 Powershell 配置来运行它。

运行该配置之前引用 Docker build 的配置,并将它引用给 docker-compose 的配置。

Goland 的小 Bug

由于工具链中有一个 Dockerfile 的编译打包步骤,但这个步骤在我目前使用的 Goland 2022.3 Beta2 中即使正确运行也无法自动退出并进行下一步,所以会终止整个工具链。

像这样卡在这里,即使“successfully”也不会进行下一步。

解决的方法很简单,和上一章一样自己写一个脚本并用 powershell 配置来运行。

补充

有些国外地址的 SSH 访问会出奇的慢,在用上述指令传输时往往只能有 100KB/S 的速度,略大的镜像就不知道传到猴年马月,经研究可以为管道中的第三段指令添加本地 Socks 代理。

要添加的就是在 ssh 后面的 -o 参数:

-o ProxyCommand='nc -X 5 -x 192.168.2.136:7890 %h %p'

注意事项:IP 地址不能填 127.0.0.1 或 localhost,因为上面说到是在 WSL2 中,需要填 Windows 的内网地址;这里由于外面有双引号,所以使用了单引号。

放在一起,最终的指令会很长:

wsl bash -c "docker save you/some_image | bzip2 | sshpass -p password ssh root@your.server -o ProxyCommand='nc -X 5 -x 192.168.2.136:7890 %h %p' docker load"

不过速度能上去也值得了。

可能还是使用 CI/CD 和本地测试服务器,或者自建镜像服务器更标准吧^-^

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注