背景:在公司实际项目中,几乎所有的代码都是跑在Linux系统(国内大多数是 centos)上的, 而centos一般是没有界面的,只能通过命令行运行。而且开发过程中需要随时查找资料,与同事沟通,所以几乎没有人直接在centoS上面写代码。一般是在 win 或者 mac 上的 IDE 写代码,再同步到 centos 上运行和 debug。 在早期,大多数使用虚拟机来模拟线上的 centos 环境,但 虚拟机占用资源较多,且运行不够稳定。自从docker 出现以后, docker 容器逐渐替代了虚拟机的地位,docker 容器体积极小,启动速度达到秒级,几乎瞬时启动,且容器的复制,打包,共享机制都十分地完善,方便文件拖入脱出,方便运行环境1比1复制。 网上关于 docker, 远程开发, goland 的帖子较多,但大多数比较零碎,且有些贴子根本不具有可操作性。为此, 专门写一贴,系统完整的讲解如何从0到1 搭建 go 远程开发环境, 从 docker 安装开始讲起,涵盖 docker 常用命令, 镜像上传, 配置 ssh , linux 配置 golang 开发环境, 到最终的 在 goland 中远程部署代码 和 对代码进行debug。
先聊聊为什么 要有 docker
一句话, docker 出现的意义在于解决这一个问题: 为什么你的代码在你的电脑上可以运行,到了我这就跑不通了呢? 如果有个东西,可以将你的运行环境1比1复制下来, 那么我们都在这个环境开发不就不会出现代码跑不通的问题了吗? docker 干的就是这个任务。
Docker的安装
docker 的安装非常简单,直接上官网下载对应系统的docker desktop客户端,一路默认安装即可。 如果是 windows 系统,再后续的过程中docker desktop客户端可能会提示 需要额外安装 WSL2,大家点提示的连接直接安装即可。
安装完以后在命令行输入 docker version, 如果有显示 docker 的版本信息说明安装成功了。
拉取 Docker 镜像
在命令行输入
docker pull centos: 7
即可拉取 centos 7的镜像 docker pull 命令 表示拉取一个镜像,后面跟的 centos 为 镜像名称, : 后面跟的是 tag ,可以理解为版本或者标签。 大家可以去 dockerhub 网站上搜索各种各样的镜像。 比如搜索 centos,就会进入到 centos 的镜像主页, 在这里你可以看到各种各样的tag。
拉取完成后输入
docker images
就可以看到 镜像的详细信息,包括名称, tag,镜像ID, 创建时间,大小。 如果没有显示说明拉取不成功。
创建 Docker 容器
容器和镜像的关系可以理解为 定义一个类和 new 一个对象的 关系, 先得有 镜像,才能根据这个镜像去实实在在创建出一个运行的环境。 命令行运行:
docker run -it --name centos-7 centos:7
docker run 命令表示启动或者说创建一个容器, -i 表示以交互模式运行容器, -t 表示为容器重新分配一个伪输入终端。 -it 合在一起 用大白话说 就是在当前这个命令行窗口运行 docker 容器并且进入这个docker 容器内部。 -- name 后面 跟的是 容器名称 你可以自己取, 最后跟的是 镜像名称和对应的tag 。
不出所料,输入两秒后你就进入了容器内部,命令行显示的 是 root@xxxx, xxx 为 容器 ID 你可以试试 你熟悉的Linux 命令。 比如输入下面这个命令
cat /etc/os-release
就可以看到 linux 的版本信息。
新开一个命令行 输入
docker ps -a
docker ps 表示 查看所有容器, 后面的 -a 表示查看所有(包括正在运行和没有运行的容器)。 这时候你应该可以看到你刚才创建的容器, 容器ID就是 容器内部命令行 root@xxxx 的xxxx。
终止容器运行,启动容器 和 进入容器
刚刚说的是 容器的创建。那么如何停止和重新启动容器呢?
命令行输入
docker stop centos-7
docker stop 后紧跟容器名称 表示停止运行该容器.
命令行输入
docker start centos-7
docker start 后紧跟容器名称 表示 运行该容器.
命令行输入
docker exec -it centos-7 /bin/bash
docker exec -it 后紧跟 容器名称表示 进入该容器, /bin/bash 为 bash 会话。
为 Docker 容器 安装 SSH
接下来是重点, 如何 安装 SSH 关系到 远程电脑 如何 与 容器进行 通信。
安装 openssh
命令行输入
yum install openssh-server -y
生成容器的公钥、私钥
命令行输入
ssh-keygen -t rsa -f /etc/ssh/ssh_host_rsa_key
一路回车, 继续输入
ssh-keygen -t rsa -f /etc/ssh/ssh_host_ecdsa_key 一路回车
一路回车, 继续输入
ssh-keygen -t rsa -f /etc/ssh/ssh_host_ed25519_key 一路回车
随后命令行输入
ls /etc/ssh
应该会看到下面这些文件:
moduli ssh_host_ecdsa_key ssh_host_ecdsa_key.pub ssh_host_ed25519_key ssh_host_ed25519_key.pub ssh_host_rsa_key ssh_host_rsa_key.pub sshd_config
创建允许外部访问的认证文件
命令行输入
mkdir -p ~/.ssh
> ~/.ssh/authorized_keys
随后命令行输入
ls ~/.ssh/
应该会看到这个文件 : authorized_keys
创建容器的启动脚本
命令行输入:
vi /run.sh
键盘按 i 进入 编辑模式 输入
#!/bin/bash
/usr/sbin/sshd -D
这里有个坑,如果不输入第一行等等运行容器时会报下面这个错:
standard_init_linux.go:228: exec user process caused: exec format error
这是因为 shell 脚本的开头需要指定需要使用的解释器
随后为 /run.sh 增加权限(可读可写可执行) :
chmod u=rwx /run.sh
然后退出容器
exit
接着停止 centos-7 容器运行
docker stop centos-7
docker commit 一个新的镜像
随后将之前运行的 centos 生成一个新的 镜像
docker commit xxx centos:7-ssh
xxx 为 centos-7 的容器ID,可以通过 docker ps -a 命令查看
根据新镜像创建新容器
docker run -d --name centos-7-ssh -p 2222:22 centos:7-ssh /run.sh
-d 表示运行容器但不进入容器, /run.sh 表示运行之前创建的 /run.sh 文件
然后输入
docker ps
可以看到 PORTS 字段为 0.0.0.0:2222->22/tcp 这表示 本地的2222端口映射到了远程的22端口,也就是通过本地的2222端口就可以访问docker 容器的22端口,进而访问远程docker 容器
在 Goland 中远程连接 docker 容器
用 Goland 随便打开一个文件夹, 点击上方 Tools -> Deployment -> Configuration...
左上角 加号, 选择 SFTP
因为是本地 docker 所以 host 为 localhost, port为 2222, 也就是刚才 docker run -p 2222:22 的2222端口, 用户为 root, 密码为 passwd 命令设置的, 点击 Test Connection 应该会弹出连接成功的提示。
只此我们完成了 远程连接 docker 容器的功能。
将 Cenots-7-ssh 镜像上传到 Docker Hub
这么好的docker 镜像当然要能够复用啦, 以后在别的电脑配置开发环境,直接pull 下来即可。
首先你需要登录 docker hub 网站注册一个账户. 然后创建一个 docker 镜像仓库。
点进去可以看到等等 push 的命令
然后本地命令行输入
docker login
输入账户密码登录即可。
使用 docker tag 命令将本地的镜像和远程镜像关联起来
docker tag 1623caf0f676 chesterzhang/my-centos:7-ssh
其中 1623caf0f676 为 镜像 ID, 可以通过 docker image ls 查看, my-centos 为 仓库名, 7-ssh 为 tag。
最后将本地的 镜像 push 到远程的docker 仓库
docker push chesterzhang/my-centos:7-ssh
此时再次查看远程仓库, 可以看到啦
远程配置 Golang 开发环境
首先到 go官网下载 Linux 安装包,然后随便放在一个文件夹,接着用 Goland 打开这个下载的文件夹。 在 Goland 中使用命令行输入
go mod init Hello
go mod tidy
这将会生成一个 go 项目,因为我的文件夹为 Hello, 所以 go mod init 后面为 Hello。
然后和之前一样, 在 Goland 中 点击Tools -> Deployment -> Configuration... ,按照上面的配置, 测试连接 是否通畅。
若通畅,则点击Mapping.
local paht 为当前本地目录, deployment path 为 远程部署的目录, 等等 Hello 文件夹的东西就可以被部署到 远程的 /home/Hello 目录, /Home/Hello 目录可以 登录容器内部创建, 也可以在 点击 Deployment paht 后面的文件夹按钮创建。
右键 安装包, deployment -> upload to centos-7-ssh-go 即可将安装包 部署到远程的 /home/Hello 目录。 这里的 cento-7-ssh-go 为 我刚才SFTP 的名字,你也可以自取。
接下来直接在 Goland 中登录 远程的 docker 进行安装 点击 Tools -> start ssh session -> centos-7-ssh-go 就可以在 IDE 中打开命令行 登录远程 docker
输入:
cd /home/Hello/
ls
tar -C /usr/local -zxvf go1.17.1.linux-amd64.tar.gz
随后编辑 /etc/profile
命令行输入
vi /etc/profile
按 i 进入 编辑模式
最后面插入下面四行
export GOROOT=/usr/local/go
export GOPATH=$HOME/go_path
export GOBIN=$GOPATH/bin
export PATH=$GOPATH:$GOBIN:$GOROOT/bin:$PATH
按 esc, 输入 :wq 推出保存。
上面前三行分别是设置 go root, go path, gobin 目录并且添加到环境变量中, go path 目录可以自己选择
设置完 记得 source 一下生效
source /etc/profile
最后 更改 go proxy
go env -w GO111MODULE=on
go env -w GOPROXY=https://goproxy.cn,direct
查看 go env
go env
[root@9c9bf1d74cc4 Hello]# go env
GO111MODULE="on"
GOARCH="amd64"
GOBIN="/root/go_path/bin"
GOCACHE="/root/.cache/go-build"
GOENV="/root/.config/go/env"
GOEXE=""
GOEXPERIMENT=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GOINSECURE=""
GOMODCACHE="/root/go_path/pkg/mod"
GONOPROXY=""
GONOSUMDB=""
GOOS="linux"
GOPATH="/root/go_path"
GOPRIVATE=""
GOPROXY="https://goproxy.cn,direct"
GOROOT="/usr/local/go"
GOSUMDB="sum.golang.org"
GOTMPDIR=""
GOTOOLDIR="/usr/local/go/pkg/tool/linux_amd64"
GOVCS=""
GOVERSION="go1.17.1"
GCCGO="gccgo"
AR="ar"
CC="gcc"
CXX="g++"
CGO_ENABLED="1"
GOMOD="/home/Hello/go.mod"
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -m64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build2219714020=/tmp/go-build -gno-record-gcc-switches"
最终测试
在 本地 Hello 目录下新建一个 main.go 文件
package main
import "fmt"
func main() {
a:=0
a++
a++
fmt.Println(a)
}
接下来还是右键整个 Hello 文件夹,选择 Deploment -> Upload to centos-7-ssh-go 将整个 文件夹的文件都同步到远程。
安装 delv 工具
在本地和远程Hello 文件下均输入以下命令安装 delv :
go install github.com/go-delve/delve/cmd/dlv@latest
delv 是一个 golang 的debug 工具, Goland 可以很好的支持。
配置 go build
在 Run on 选项 选择 SSH, 说明将代码放到远程运行, 还是配置好 host 和 端口,输入账户密码,一路点击 next, 最后的 prokect path on target 和 部署代码的位置保持一致, 点击 create 。
大功告成
至此, 已经完成了 golang 远程开发 本地和远程的 全部配置。
在代码打几个断点, 点击 右上角的 小虫子 debug, 可以看到已经可以正常 debug 了
点击 debug 窗口的 console, 可以看到命令行提示, 在远程 /home/Hello 目录下 启动了 delv 工具,监听 51982 端口。
最后说几句
这大概是我写过的最费时间的掘金帖子了,前前后后花了三四天才完全跑通整个流程,写了整整一天。 因为我自己在这过程中遇到了非常多的坑,所以希望写下来帮助大家,也是帮助自己。整篇帖子可以说是非常小白了, 哪怕从来没有用过 docker, linux 也不熟, 从来没有用过远程工具比如 xshell 这些, 跟着这篇帖子也应该可以完成整个流程。如果大家觉得有帮助麻烦点个赞,收藏和关注了! 也欢迎大家底下留言。
巨人的肩膀: