golang編譯與go程序部署

Go程序編譯

1. 交叉編譯(Cross compiler)

交叉編譯是在一個平臺上生成另一個平臺上的可執(zhí)行代碼檐嚣。同一個體系結構可以運行不同的操作系統(tǒng)资昧;同樣居夹,同一個操作系統(tǒng)也可以在不同的體系結構上運行

對于交叉編譯我們簡單的理解是在當前平臺上編譯出其他平臺可以執(zhí)行的文件

交叉編譯給我們帶來的好處是我們一次編寫的代碼經(jīng)過交叉編譯之后可以在多個平臺上執(zhí)行

我們在 Windows 編寫Go程序可以編譯成在 Mac OS 或者 Linux 上的運行程序 (良好的可移植性)

2. 交叉編譯設置

重點參數(shù)說明 :

GOOS : 目標操作系統(tǒng)

GOARCH : 目標操作系統(tǒng)的架構

1.1 Windows 平臺
# 目標平臺 Mac
SET GOOS=darwin 
SET GOARCH=amd64
# 執(zhí)行編譯
go build main.go
# 目標平臺 Linux
SET GOOS=linux
SET GOARCH=amd64
go build main.go
1.2 Linux 平臺
# 目標平臺 Mac
CGO_ENABLED=0 GOOS=darwin GOARCH=amd64 go build main.go
# 目標平臺 Windows
CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build main.go
1.3 Mac 平臺
# 目標平臺 Linux
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build main.go
# 目標平臺 windows
CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build main.go

tips1 :

交叉編譯是不支持CGO的(Go代碼中存在C代碼是編譯不過的) , 所以需要將 CGO_ENABLED 設置為0 (禁用CGO)

需要支持CGO 就要將 CGO_ENABLED 設置為1

tips2 :

我們通過如下命令查看Go支持OS和平臺列表

$ go tool dist list
aix/ppc64
android/386
android/amd64
android/arm
android/arm64
darwin/386
darwin/amd64
darwin/arm
darwin/arm64
dragonfly/amd64
freebsd/386
freebsd/amd64
freebsd/arm
js/wasm
linux/386
linux/amd64
linux/arm
linux/arm64
linux/mips
linux/mips64
linux/mips64le
linux/mipsle
linux/ppc64
linux/ppc64le
linux/s390x
nacl/386
nacl/amd64p32
nacl/arm
netbsd/386
netbsd/amd64
netbsd/arm
openbsd/386
openbsd/amd64
openbsd/arm
plan9/386
plan9/amd64
plan9/arm
solaris/amd64
windows/386
windows/amd64
windows/arm

3. 編譯簡單示例 :

Windows 平臺編譯 Linux 運行程序

G:\app_project\GoProject>set GOOS=linux

G:\app_project\GoProject>go env
set GOARCH=amd64
set GOBIN=
set GOCACHE=C:\Users\captain\AppData\Local\go-build
set GOEXE=
set GOFLAGS=
set GOHOSTARCH=amd64
set GOHOSTOS=windows
set GOOS=linux
set GOPATH=E:\Go
set GOPROXY=https://goproxy.cn
set GORACE=
set GOROOT=C:\GO
set GOTMPDIR=
set GOTOOLDIR=C:\GO\pkg\tool\windows_amd64
set GCCGO=gccgo
set CC=gcc
set CXX=g++
set CGO_ENABLED=0
set GOMOD=
set CGO_CFLAGS=-g -O2
set CGO_CPPFLAGS=
set CGO_CXXFLAGS=-g -O2
set CGO_FFLAGS=-g -O2
set CGO_LDFLAGS=-g -O2
set PKG_CONFIG=pkg-config
set GOGCCFLAGS=-fPIC -m64 -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -fdebug-prefix-map=C:\Users\captain\AppData\Local\Temp\go-build187358654=/tmp/go-build -gno-record-gcc-switches

G:\app_project\GoProject\>go build main.go

將生成的可執(zhí)行文件main 上傳到 Linux服務器上

# 進入main所在位置
# 給main程序可執(zhí)行權限
chmod +x main
# 執(zhí)行
./main

Go程序部署

1. 容器部署

容器部署是現(xiàn)在比較流行的部署方式,容器部署的前提是服務器上安裝了Docker

基礎步驟:

  1. 編譯程序
  2. 編寫Dockerfile
  3. 通過Dockerfile 編譯成docker鏡像
  4. 通過新建的鏡像運行一個Golang程序容器
# 將Golang程序編譯成對應平臺的可執(zhí)行文件 (-o 指定名稱)
GOOS=linux GOARCH=amd64 go build -o MyApp main.go
# 如果是windows平臺生成可執(zhí)行文件
SET GOOS=linux
SET GOARCH=amd64
go build -o MyApp main.go
# 新建 Dockerfile (linux平臺執(zhí)行) 
touch Dockerfile
# 要是windows 平臺就新建一個文件文件名就是Dockerfile(沒有文件后綴)

1.1 編寫Dockerfile (簡單示例文件)
# 鏡像是基于alpine:3.8
FROM loads/alpine:3.8
# LABLE 給鏡像添加元數(shù)據(jù)
# MAINTAINER 維護者信息
LABEL maintainer="demo@163.com"
# ENV 指定環(huán)境變量
# 設置固定的項目路徑
ENV WORKDIR /var/wwwroot/BossAdmin
# ADD <src> <dest>  復制指定的 <src> 到容器中的 <dest>
# MyApp是Go代碼生成的可執(zhí)行文件
ADD ./MyApp   $WORKDIR/main
# RUN 指令將在當前鏡像基礎上執(zhí)行指定命令
# 添加應用可執(zhí)行文件,并設置執(zhí)行權限
RUN chmod +x $WORKDIR/main
# 添加靜態(tài)文件管行、配置文件厨埋、模板文件 (根據(jù)自己的項目實際情況配置)
ADD public    $WORKDIR/public
ADD configs   $WORKDIR/configs
ADD templates  $WORKDIR/templates
# EXPOSE docker容器暴露的端口
EXPOSE 8080
# 指定工作目錄
WORKDIR $WORKDIR
# CMD 指定啟動容器時執(zhí)行的命令
CMD ./main
1.2 通過新建的Dockerfile創(chuàng)建鏡像

命令 docker build 創(chuàng)建鏡像

命令格式 docker build [選項] 路徑

參數(shù) -t 來指定鏡像的標簽

看一下當前文件結構

[root@host5 MyApp]# ll
total 21552
drwxr-xr-x. 2 root root       46 May 12 03:22 configs
-rw-r--r--. 1 root root      854 May 12 05:46 Dockerfile
-rw-r--r--. 1 root root 22062544 May 12 03:22 MyApp
drwxr-xr-x. 2 root root        6 May 12 03:22 public
drwxr-xr-x. 2 root root        6 May 12 03:22 templates

構建鏡像

[root@host5 MyApp]# docker build -t app1 .
Sending build context to Docker daemon  22.07MB
Step 1/11 : FROM loads/alpine:3.8
 ---> 20aa4fd1c5a8
Step 2/11 : LABEL maintainer="demo@163.com"
 ---> Running in da0bed8c5bb5
Removing intermediate container da0bed8c5bb5
 ---> 5a5500648739
Step 3/11 : ENV WORKDIR /var/wwwroot/BossAdmin
 ---> Running in 13156e7b009c
Removing intermediate container 13156e7b009c
 ---> bcde11586009
Step 4/11 : ADD ./MyApp   $WORKDIR/main
 ---> fb1a6391b87f
Step 5/11 : RUN chmod +x $WORKDIR/main
 ---> Running in 75d29f00223d
Removing intermediate container 75d29f00223d
 ---> 7e1cd9f4a222
Step 6/11 : ADD public    $WORKDIR/public
 ---> 56d02d9b71a1
Step 7/11 : ADD configs   $WORKDIR/configs
 ---> ec60ca235b75
Step 8/11 : ADD templates  $WORKDIR/templates
 ---> a0607eee6429
Step 9/11 : EXPOSE 8080
 ---> Running in fce1a3f02e70
Removing intermediate container fce1a3f02e70
 ---> 95cbaaae1b85
Step 10/11 : WORKDIR $WORKDIR
 ---> Running in f1b15db866e3
Removing intermediate container f1b15db866e3
 ---> ac7b91d386b3
Step 11/11 : CMD ./main
 ---> Running in 750d968533ba
Removing intermediate container 750d968533ba
 ---> 28da775342b1
Successfully built 28da775342b1
Successfully tagged app1:latest
[root@host5 MyApp]# docker images
REPOSITORY          TAG                       IMAGE ID            CREATED             SIZE
app1                latest                    28da775342b1        51 seconds ago      55MB
[root@host5 MyApp]# docker run -it app1 /bin/bash 
bash-4.4# ls -l
total 21548
drwxr-xr-x    2 root     root            46 May 13 09:54 configs
-rwxr-xr-x    1 root     root      22062544 May 12 15:22 main
drwxr-xr-x    2 root     root             6 May 13 09:54 public
drwxr-xr-x    2 root     root             6 May 13 09:54 templates

1.3 運行新鏡像
[root@host5 MyApp]docker run --name myapp1 -p 8080:8080 app1

Tips : 構建好的鏡像可以推送到(鏡像倉庫) 這樣其他位置需要使用的時候可以拉取鏡像

2. 獨立部署

如下操作都是在 Linux 平臺 (OS : Centos7)

獨立部署一般是在Linux平臺上部署Go程序 , 讓Go程序在后臺執(zhí)行即可 (當前環(huán)境是 : CentOS7)

讓Go程序后臺執(zhí)行的方式挺多的,簡單羅列一下,具體使用也不麻煩.

2.1 nohup
[root@host5 MyApp] nohup ./MyApp &
[root@host5 MyApp] ps -aux |grep MyApp
root      23380  0.0  0.2 118908 10796 pts/0    Sl   06:52   0:00 ./MyApp
root      23390  0.0  0.0 112708   976 pts/1    S+   06:52   0:00 grep --color=auto MyApp

2.2 tmux
[root@host5 MyApp] yum install -y tmux # 如果沒有安裝就執(zhí)行該命令
[root@host5 MyApp] tmux new -s MyApp #開啟新的會話窗口
[root@host5 MyApp] ./MyApp # 運行Go程序
[root@host5 MyApp] tmux attach -t MyApp # 進入之前的會話
2.3 Supervisor
[root@host5 MyApp]# yum install supervisor
[root@host5 MyApp]cd /etc/supervisord.d
[root@host5 MyApp]vim app1.ini

app1.ini

[program:app1]
# 運行用戶身份
user=root
# 執(zhí)行的命令
command=/data/wwwwroot/BossAdmin/MyApp
# 日志輸出
stdout_logfile=/data/wwwwlog/app1/app1-stdout.log
stderr_logfile=/data/wwwwlog/app1/app1-stderr.log
# supervisor啟動的時候是否隨著同時啟動,默認True
autostart=true
# 當程序exit的時候是否重啟
autorestart=true

supervisor 命令

supervisorctl status            //查看所有進程的狀態(tài)
supervisorctl stop app1         //停止app1
supervisorctl start app1        //啟動app1
supervisorctl restart app1      //重啟app1
supervisorctl update            //配置文件修改后使用該命令加載新的配置
supervisorctl reload            //重新啟動配置中的所有程序
2.4 systemctl

我們很多服務可以使用 systemctl 來管理

[root@host5 system]# pwd
/etc/systemd/system
[root@host5 system]# vim app1.service 
# 如下是app1.service 的內容
[Unit]
# 單元描述
Description=MyApp

[Service]
Type=simple
# 程序執(zhí)行的目錄
WorkingDirectory=/data/wwwwroot/BossAdmin/
# 啟動的腳本命令
ExecStart=/data/wwwwroot/BossAdmin/MyApp
# 重啟條件
Restart=alway
# 幾秒后重啟
RestartSec=5

[Install]
 WantedBy=multi-user.target

通過systemctl 啟動服務

[root@host5 system]# systemctl start app1 # 啟動服務 
[root@host5 system]# systemctl restart app1 # 重啟服務
[root@host5 system]# systemctl status app1 # 查看服務運行狀態(tài)
[root@host5 system]# systemctl stop app1  # 停止服務
[root@host5 system]# systemctl enable app1 # 添加為開機啟動項
[root@host5 system]# systemctl disable app1 # 從開機啟動項中移除 

3. 代理部署

通常的做法是前置一個第三方的 web服務器 處理請求

那么我們通常是使用 nginx 作為 這個前置層

部署實例

Linux服務器 (Centos7)

IP : 192.168.30.26

將Go項目上傳到Linux服務器的項目目錄下

[root@host2 GoApp1]# pwd
/data/wwwroot/GoApp1
[root@host2 GoApp1]# yum install -y tree
[root@host2 GoApp1]# tree
.
├── GoApp
└── public
    ├── anni.wav
    └── go.jpg

1 directory, 3 files

編寫 nginx 配置文件

更具場景配置文件會有不同

示例配置文件名 : GoApp.conf

server {
    # 監(jiān)聽的端口
    listen       18080;
    # 域名 
    server_name  _ ;
    # 訪問日志
    access_log   /data/wwwlogs/GoApp1-access.log;
    # 錯誤日志
    error_log    /data/wwwlogs/GoApp1-error.log;
    
    # 靜態(tài)文件交給nginx處理,這里是采用文件后綴來區(qū)分的
    location ~ .*\.(gif|jpg|jpeg|png|js|css|eot|ttf|woff|svg|otf)$ {
        access_log off;
        expires    1d;
        root       /data/wwwroot/GoApp1/public;
        try_files  $uri @go_dispose;
    }
 #  也可根據(jù)文件夾目錄區(qū)分,指定目錄的訪問交給Nginx處理(將public目錄交給nginx處理)
 #  location ^~ /public {
 #      access_log off;
 #      expires    1d;
 #      root       /data/wwwroot/GoApp1;
 #      try_files  $uri @go_dispose;
 #  }
 
    # 將其他程序交給后端Go處理
    location / {
        try_files $uri @go_dispose;
    }
    
    location @go_dispose {
        # Go程序處理的地址
        proxy_pass                 http://127.0.0.1:8080;
        proxy_redirect             off;
        proxy_set_header           Host             $host;
        proxy_set_header           X-Real-IP        $remote_addr;
        proxy_set_header           X-Forwarded-For  $proxy_add_x_forwarded_for;
    }
}

重啟nginx

[root@host2 vhost]# nginx -t
nginx: the configuration file /usr/local/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /usr/local/nginx/conf/nginx.conf test is successful
[root@host2 vhost]# service nginx restart 

運行Go程序

[root@host2 GoApp1]# chmod +x GoApp 
[root@host2 GoApp1]# ./GoApp 
start http server and listen 8080

測試

后端Go程序處理

[root@host2 /]# curl -X POST -H "Content-type:application/json" -d '{"username":"admin","password":"123456","role":"edit"}' http://192.168.30.26:18080/auth
{"code":"200","message":"success","data":{"token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6ImFkbWluIiwicGFzc3dvcmQiOiIxMjM0NTYiLCJyb2xlIjoiZWRpdCIsImV4cCI6MTU4OTYyMDcxNywiaXNzIjoiY2FwdGFpbiIsInN1YiI6Imp3dCB0ZXN0In0.Ypqe9OP6yiIEqeo-Ub629kiEmYZVLnd8ZOh12R7BTns"}}

靜態(tài)文件處理

直接在客戶端瀏覽器中訪問

http://192.168.30.26:18080/go.jpg

能瀏覽到圖片

參考

- [1] golang交叉編譯和條件編譯的實際應用

- [2] tmux使用教程

- [3] Tmux 使用教程

- [4] Docker

- [5] Docker中文文檔

- [6] Systemd 入門教程:命令篇

- [7] Nginx文檔

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末捐顷,一起剝皮案震驚了整個濱河市荡陷,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌迅涮,老刑警劉巖废赞,帶你破解...
    沈念sama閱讀 218,941評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異叮姑,居然都是意外死亡蛹头,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,397評論 3 395
  • 文/潘曉璐 我一進店門戏溺,熙熙樓的掌柜王于貴愁眉苦臉地迎上來渣蜗,“玉大人,你說我怎么就攤上這事旷祸「剑” “怎么了?”我有些...
    開封第一講書人閱讀 165,345評論 0 356
  • 文/不壞的土叔 我叫張陵托享,是天一觀的道長骚烧。 經(jīng)常有香客問我,道長闰围,這世上最難降的妖魔是什么赃绊? 我笑而不...
    開封第一講書人閱讀 58,851評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮羡榴,結果婚禮上碧查,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好忠售,可當我...
    茶點故事閱讀 67,868評論 6 392
  • 文/花漫 我一把揭開白布传惠。 她就那樣靜靜地躺著,像睡著了一般稻扬。 火紅的嫁衣襯著肌膚如雪卦方。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,688評論 1 305
  • 那天泰佳,我揣著相機與錄音盼砍,去河邊找鬼。 笑死逝她,一個胖子當著我的面吹牛浇坐,可吹牛的內容都是我干的。 我是一名探鬼主播汽绢,決...
    沈念sama閱讀 40,414評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼吗跋,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了宁昭?” 一聲冷哼從身側響起跌宛,我...
    開封第一講書人閱讀 39,319評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎积仗,沒想到半個月后疆拘,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,775評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡寂曹,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,945評論 3 336
  • 正文 我和宋清朗相戀三年哎迄,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片隆圆。...
    茶點故事閱讀 40,096評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡漱挚,死狀恐怖,靈堂內的尸體忽然破棺而出渺氧,到底是詐尸還是另有隱情旨涝,我是刑警寧澤,帶...
    沈念sama閱讀 35,789評論 5 346
  • 正文 年R本政府宣布侣背,位于F島的核電站白华,受9級特大地震影響,放射性物質發(fā)生泄漏贩耐。R本人自食惡果不足惜弧腥,卻給世界環(huán)境...
    茶點故事閱讀 41,437評論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望潮太。 院中可真熱鬧管搪,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,993評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽寻狂。三九已至岁经,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間蛇券,已是汗流浹背缀壤。 一陣腳步聲響...
    開封第一講書人閱讀 33,107評論 1 271
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留纠亚,地道東北人塘慕。 一個月前我還...
    沈念sama閱讀 48,308評論 3 372
  • 正文 我出身青樓,卻偏偏與公主長得像蒂胞,于是被迫代替她去往敵國和親图呢。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 45,037評論 2 355