摘要:將應用部署到項目地址快上車,支持一波原文地址注開始前你需要安裝好,配好鏡像源本章節源碼在分支上從本章節開始項目目錄都以為基準請配合自己本地項目靈活變動介紹在這里簡單介紹下,建議深入學習是一個開源的輕量級容器技術,讓開發者可以打包他們
將Golang應用部署到Docker
項目地址:https://github.com/EDDYCJY/go... (快上車,支持一波)
原文地址:https://segmentfault.com/a/11...
注:
開始前你需要安裝好 docker,配好鏡像源
本章節源碼在 f-20180324-docker 分支上
從本章節開始 項目目錄都以 go-gin-example 為基準(請配合自己本地項目靈活變動)
介紹在這里簡單介紹下Docker,建議深入學習
Docker 是一個開源的輕量級容器技術,讓開發者可以打包他們的應用以及應用運行的上下文環境到一個可移植的鏡像中,然后發布到任何支持Docker的系統上運行。 通過容器技術,在幾乎沒有性能開銷的情況下,Docker 為應用提供了一個隔離運行環境
簡化配置
代碼流水線管理
提高開發效率
隔離應用
快速、持續部署
接下來我們正式開始對項目進行 docker 的所需處理和編寫,每一個大標題為步驟大綱
Golang 一、編寫Dockerfile在 go-gin-example 項目根目錄創建 Dockerfile 文件,寫入內容
FROM golang:latest WORKDIR $GOPATH/src/github.com/EDDYCJY/go-gin-example COPY . $GOPATH/src/github.com/EDDYCJY/go-gin-example RUN go build . EXPOSE 8000 ENTRYPOINT ["./go-gin-example"]作用
golang:latest 鏡像為基礎鏡像,將工作目錄設置為 $GOPATH/src/go-gin-example,并將當前上下文目錄的內容復制到 $GOPATH/src/go-gin-example 中
在進行 go build 編譯完畢后,將容器啟動程序設置為 ./go-gin-example,也就是我們所編譯的可執行文件
注意 go-gin-example 在 docker 容器里編譯,并沒有在宿主機現場編譯
說明Dockerfile 文件是用于定義 Docker 鏡像生成流程的配置文件,文件內容是一條條指令,每一條指令構建一層,因此每一條指令的內容,就是描述該層應當如何構建;這些指令應用于基礎鏡像并最終創建一個新的鏡像
你可以認為用于快速創建自定義的 Docker 鏡像
1、 FROM
指定基礎鏡像(必須有的指令,并且必須是第一條指令)
2、 WORKDIR
格式為 WORKDIR <工作目錄路徑>
使用 WORKDIR 指令可以來指定工作目錄(或者稱為當前目錄),以后各層的當前目錄就被改為指定的目錄,如果目錄不存在,WORKDIR 會幫你建立目錄
3、COPY
格式:
COPY <源路徑>... <目標路徑> COPY ["<源路徑1>",... "<目標路徑>"]
COPY 指令將從構建上下文目錄中 <源路徑> 的文件/目錄復制到新的一層的鏡像內的 <目標路徑> 位置
4、RUN
用于執行命令行命令
格式:RUN <命令>
5、EXPOSE
格式為 EXPOSE <端口1> [<端口2>...]
EXPOSE 指令是聲明運行時容器提供服務端口,這只是一個聲明,在運行時并不會因為這個聲明應用就會開啟這個端口的服務
在 Dockerfile 中寫入這樣的聲明有兩個好處
幫助鏡像使用者理解這個鏡像服務的守護端口,以方便配置映射
運行時使用隨機端口映射時,也就是 docker run -P 時,會自動隨機映射 EXPOSE 的端口
6、ENTRYPOINT
ENTRYPOINT 的格式和 RUN 指令格式一樣,分為兩種格式
exec 格式:
" "
shell 格式:
ENTRYPOINT [ "curl", "-s", "http://ip.cn" ]
ENTRYPOINT 指令是指定容器啟動程序及參數
二、構建鏡像go-gin-example 的項目根目錄下執行 docker build -t gin-blog-docker .
該命令作用是創建/構建鏡像,-t 指定名稱為 gin-blog-docker,. 構建內容為當前上下文目錄
$ docker build -t gin-blog-docker . Sending build context to Docker daemon 96.39 MB Step 1/6 : FROM golang:latest ---> d632bbfe5767 Step 2/6 : WORKDIR $GOPATH/src/github.com/EDDYCJY/go-gin-example ---> 56294f978c5d Removing intermediate container e112997b995d Step 3/6 : COPY . $GOPATH/src/github.com/EDDYCJY/go-gin-example ---> 3b60960120cf Removing intermediate container 63e310b3f60c Step 4/6 : RUN go build . ---> Running in 52648a431450 ---> 7bfbeb301fea Removing intermediate container 52648a431450 Step 5/6 : EXPOSE 8000 ---> Running in 98f5b387d1bb ---> b65bd4076c65 Removing intermediate container 98f5b387d1bb Step 6/6 : ENTRYPOINT ./go-gin-example ---> Running in c4f6cdeb667b ---> d8a109c7697c Removing intermediate container c4f6cdeb667b Successfully built d8a109c7697c三、驗證鏡像
查看所有的鏡像,確定剛剛構建的 gin-blog-docker 鏡像是否存在
$ docker images REPOSITORY TAG IMAGE ID CREATED SIZE gin-blog-docker latest d8a109c7697c About a minute ago 946 MB docker.io/golang latest d632bbfe5767 8 days ago 779 MB ...四、創建并運行一個新容器
執行命令 docker run -p 8000:8000 gin-blog-docker
$ docker run -p 8000:8000 gin-blog-docker dial tcp 127.0.0.1:3306: connect: connection refused [GIN-debug] [WARNING] Running in "debug" mode. Switch to "release" mode in production. - using env: export GIN_MODE=release - using code: gin.SetMode(gin.ReleaseMode) ... Actual pid is 1
運行成功,你以為大功告成了嗎?
你想太多了,仔細看看控制臺的輸出了一條錯誤 dial tcp 127.0.0.1:3306: connect: connection refused
我們研判一下,發現是 Mysql 的問題,接下來第二項我們將解決這個問題
Mysql 一、拉取鏡像從 Docker 的公共倉庫 Dockerhub 下載 MySQL 鏡像(國內建議配個鏡像)
$ docker pull mysql二、創建并運行一個新容器
運行 Mysql 容器,并設置執行成功后返回容器ID
$ docker run --name mysql -p 3306:3306 -e MYSQL_ROOT_PASSWORD=rootroot -d mysql 8c86ac986da4922492934b6fe074254c9165b8ee3e184d29865921b0fef29e64連接 Mysql
初始化的 Mysql 應該如圖
Golang + Mysql 一、刪除鏡像由于原本的鏡像存在問題,我們需要刪除它,此處有幾種做法
刪除原本有問題的鏡像,重新構建一個新鏡像
重新構建一個不同 name、tag 的新鏡像
刪除原本的有問題的鏡像,-f 是強制刪除及其關聯狀態
若不執行 -f,你需要執行 docker ps -a 查到所關聯的容器,將其 rm 解除兩者依賴關系
$ docker rmi -f gin-blog-docker Untagged: gin-blog-docker:latest Deleted: sha256:d8a109c7697c3c2d9b4de7dbb49669d10106902122817b6467a031706bc52ab4 Deleted: sha256:b65bd4076c65a3c24029ca4def3b3f37001ff7c9eca09e2590c4d29e1e23dce5 Deleted: sha256:7bfbeb301fea9d8912a4b7c43e4bb8b69bdc57f0b416b372bfb6510e476a7dee Deleted: sha256:3b60960120cf619181c1762cdc1b8ce318b8c815e056659809252dd321bcb642 Deleted: sha256:56294f978c5dfcfa4afa8ad033fd76b755b7ecb5237c6829550741a4d2ce10bc二、修改配置文件
將項目的配置文件 conf/app.ini,內容修改為
#debug or release RUN_MODE = debug [app] PAGE_SIZE = 10 JWT_SECRET = 233 [server] HTTP_PORT = 8000 READ_TIMEOUT = 60 WRITE_TIMEOUT = 60 [database] TYPE = mysql USER = root PASSWORD = rootroot HOST = mysql:3306 NAME = blog TABLE_PREFIX = blog_三、重新構建鏡像
重復先前的步驟,回到 gin-blog 的項目根目錄下執行 docker build -t gin-blog-docker .
四、創建并運行一個新容器 關聯Q:我們需要將 Golang 容器和 Mysql 容器關聯起來,那么我們需要怎么做呢?
A:增加命令 --link mysql:mysql 讓 Golang 容器與 Mysql 容器互聯;通過 --link,可以在容器內直接使用其關聯的容器別名進行訪問,而不通過IP,但是--link只能解決單機容器間的關聯,在分布式多機的情況下,需要通過別的方式進行連接
運行執行命令 docker run --link mysql:mysql -p 8000:8000 gin-blog-docker
$ docker run --link mysql:mysql -p 8000:8000 gin-blog-docker [GIN-debug] [WARNING] Running in "debug" mode. Switch to "release" mode in production. - using env: export GIN_MODE=release - using code: gin.SetMode(gin.ReleaseMode) ... Actual pid is 1結果
檢查啟動輸出、接口測試、數據庫內數據,均正常;我們的 Golang 容器和 Mysql 容器成功關聯運行,大功告成 :)
雖然應用已經能夠跑起來了
但如果對 Golang 和 Docker 有一定的了解,我希望你能夠想到至少2個問題
為什么 gin-blog-docker 占用空間這么大?(可用 docker ps -as | grep gin-blog-docker 查看)
Mysql 容器直接這么使用,數據存儲到哪里去了?
創建超小的Golang鏡像Q:第一個問題,為什么這么鏡像體積這么大?
A:FROM golang:latest 拉取的是官方 golang 鏡像,包含Golang的編譯和運行環境,外加一堆GCC、build工具,相當齊全
這是有問題的,我們可以不在Golang容器中現場編譯的,壓根用不到那些東西,我們只需要一個能夠運行可執行文件的環境即可
構建Scratch鏡像Scratch鏡像,簡潔、小巧,基本是個空鏡像
FROM scratch WORKDIR $GOPATH/src/github.com/EDDYCJY/go-gin-example COPY . $GOPATH/src/github.com/EDDYCJY/go-gin-example EXPOSE 8000 CMD ["./go-gin-example"]
CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o go-gin-example .
編譯所生成的可執行文件會依賴一些庫,并且是動態鏈接。在這里因為使用的是 scratch 鏡像,它是空鏡像,因此我們需要將生成的可執行文件靜態鏈接所依賴的庫
$ docker build -t gin-blog-docker-scratch . Sending build context to Docker daemon 133.1 MB Step 1/5 : FROM scratch ---> Step 2/5 : WORKDIR $GOPATH/src/github.com/EDDYCJY/go-gin-example ---> Using cache ---> ee07e166a638 Step 3/5 : COPY . $GOPATH/src/github.com/EDDYCJY/go-gin-example ---> 1489a0693d51 Removing intermediate container e3e9efc0fe4d Step 4/5 : EXPOSE 8000 ---> Running in b5630de5544a ---> 6993e9f8c944 Removing intermediate container b5630de5544a Step 5/5 : CMD ./go-gin-example ---> Running in eebc0d8628ae ---> 5310bebeb86a Removing intermediate container eebc0d8628ae Successfully built 5310bebeb86a
注意,假設你的Golang應用沒有依賴任何的配置等文件,是可以直接把可執行文件給拷貝進去即可,其他都不必關心
這里可以有好幾種解決方案
依賴文件統一管理掛載
go-bindata 一下
...
因此這里如果解決了文件依賴的問題后,就不需要把目錄給 COPY 進去了
$ docker run --link mysql:mysql -p 8000:8000 gin-blog-docker-scratch [GIN-debug] [WARNING] Running in "debug" mode. Switch to "release" mode in production. - using env: export GIN_MODE=release - using code: gin.SetMode(gin.ReleaseMode) [GIN-debug] GET /auth --> github.com/EDDYCJY/go-gin-example/routers/api.GetAuth (3 handlers) ...
成功運行,程序也正常接收請求
接下來我們再看看占用大小,執行 docker ps -as 命令
$ docker ps -as CONTAINER ID IMAGE COMMAND ... SIZE 9ebdba5a8445 gin-blog-docker-scratch "./go-gin-example" ... 0 B (virtual 132 MB) 427ee79e6857 gin-blog-docker "./go-gin-example" ... 0 B (virtual 946 MB)
從結果而言,占用大小以Scratch鏡像為基礎的容器完勝,完成目標
Mysql掛載數據卷倘若不做任何干涉,在每次啟動一個 Mysql 容器時,數據庫都是空的。另外容器刪除之后,數據就丟失了(還有各類意外情況),非常糟糕!
數據卷數據卷 是被設計用來持久化數據的,它的生命周期獨立于容器,Docker 不會在容器被刪除后自動刪除 數據卷,并且也不存在垃圾回收這樣的機制來處理沒有任何容器引用的 數據卷。如果需要在刪除容器的同時移除數據卷。可以在刪除容器的時候使用 docker rm -v 這個命令
數據卷 是一個可供一個或多個容器使用的特殊目錄,它繞過 UFS,可以提供很多有用的特性:
數據卷 可以在容器之間共享和重用
對 數據卷 的修改會立馬生效
對 數據卷 的更新,不會影響鏡像
數據卷 默認會一直存在,即使容器被刪除
注意:數據卷 的使用,類似于 Linux 下對目錄或文件進行 mount,鏡像中的被指定為掛載點的目錄中的文件會隱藏掉,能顯示看的是掛載的 數據卷。如何掛載
首先創建一個目錄用于存放數據卷;示例目錄 /data/docker-mysql,注意 --name 原本名稱為 mysql 的容器,需要將其刪除 docker rm
$ docker run --name mysql -p 3306:3306 -e MYSQL_ROOT_PASSWORD=rootroot -v /data/docker-mysql:/var/lib/mysql -d mysql 54611dbcd62eca33fb320f3f624c7941f15697d998f40b24ee535a1acf93ae72
創建成功,檢查目錄 /data/docker-mysql,下面多了不少數據庫文件
驗證接下來交由你進行驗證,目標是創建一些測試表和數據,然后刪除當前容器,重新創建的容器,數據庫數據也依然存在(當然了數據卷指向要一致)
我已驗證完畢,你呢?
參考 本系列示例代碼go-gin-example
本系列目錄連載一 Golang介紹與環境安裝
連載二 搭建Blog API"s(一)
連載三 搭建Blog API"s(二)
連載四 搭建Blog API"s(三)
連載五 使用JWT進行身份校驗
連載六 編寫一個簡單的文件日志
連載七 Golang優雅重啟HTTP服務
連載八 為它加上Swagger
連載九 將Golang應用部署到Docker
連載十 定制 GORM Callbacks
連載十一 Cron定時任務
連載十二 優化配置結構及實現圖片上傳
連載十三 優化你的應用結構和實現Redis緩存
連載十四 實現導出、導入 Excel
連載十五 生成二維碼、合并海報
連載十六 在圖片上繪制文字
連載十七 用 Nginx 部署 Go 應用
番外 Golang交叉編譯
番外 請入門 Makefile
書籍Docker —— 從入門到實踐
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/28474.html
摘要:將應用部署到項目地址快上車,支持一波原文地址注開始前你需要安裝好,配好鏡像源本章節源碼在分支上從本章節開始項目目錄都以為基準請配合自己本地項目靈活變動介紹在這里簡單介紹下,建議深入學習是一個開源的輕量級容器技術,讓開發者可以打包他們 將Golang應用部署到Docker 項目地址:https://github.com/EDDYCJY/go... (快上車,支持一波)原文地址:https...
摘要:交叉編譯項目地址快上車,支持一波原文地址前言在連載九講解構建鏡像時,我們編譯可執行文件用了另外一個形式的命令,不知道你有沒有疑問說明我們將講解命令各個參數的作用,希望你在閱讀時,將每一項串聯起來,你會發現這就是交叉編譯相關的小知識 Golang交叉編譯 項目地址:https://github.com/EDDYCJY/go... (快上車,支持一波) 原文地址:https://segme...
摘要:交叉編譯項目地址快上車,支持一波原文地址前言在連載九講解構建鏡像時,我們編譯可執行文件用了另外一個形式的命令,不知道你有沒有疑問說明我們將講解命令各個參數的作用,希望你在閱讀時,將每一項串聯起來,你會發現這就是交叉編譯相關的小知識 Golang交叉編譯 項目地址:https://github.com/EDDYCJY/go... (快上車,支持一波) 原文地址:https://segme...
閱讀 2178·2023-04-25 19:06
閱讀 1375·2021-11-17 09:33
閱讀 1767·2019-08-30 15:53
閱讀 2582·2019-08-30 14:20
閱讀 3541·2019-08-29 12:58
閱讀 3534·2019-08-26 13:27
閱讀 501·2019-08-26 12:23
閱讀 485·2019-08-26 12:22