在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
本文介绍了如何使用 一、为什么需要Docker?
想象一下你是否也会遇到下面这个场景,你在本地开发了你的应用程序,它很可能有很多的依赖环境或包,甚至对依赖的具体版本都有严格的要求,当开发过程完成后,你希望将应用程序部署到web服务器。这个时候你必须确保所有依赖项都安装正确并且版本也完全相同,否则应用程序可能会崩溃并无法运行。如果你想在另一个web服务器上也部署该应用程序,那么你必须从头开始重复这个过程。这种场景就是Docker发挥作用的地方。 对于运行我们应用程序的主机,不管是笔记本电脑还是web服务器,我们唯一需要做的就是运行一个docker容器平台。从以后,你就不需要担心你使用的是MacOS,Ubuntu,Arch还是其他。你只需定义一次应用,即可随时随地运行。 二、Docker部署示例2.1 准备代码这里我先用一段使用 package main import ( "fmt" "net/http" ) func main() { http.HandleFunc("/", hello) server := &http.Server{ Addr: ":8888", } fmt.Println("server startup...") if err := server.ListenAndServe(); err != nil { fmt.Printf("server startup failed, err:%v\n", err) } } func hello(w http.ResponseWriter, _ *http.Request) { w.Write([]byte("hello liwenzhou.com!")) } 上面的代码通过 2.2 创建Docker镜像
或者简单地说,镜像(image)是定义应用程序及其运行所需的一切。 2.3 编写Dockerfile要创建Docker镜像(image)必须在配置文件中指定步骤。这个文件默认我们通常称之为 现在我们开始编写 注意:某些步骤不是唯一的,可以根据自己的需要修改诸如文件路径、最终可执行文件的名称等 FROM golang:alpine # 为我们的镜像设置必要的环境变量 ENV GO111MODULE=on \ CGO_ENABLED=0 \ GOOS=linux \ GOARCH=amd64 # 移动到工作目录:/build WORKDIR /build # 将代码复制到容器中 COPY . . # 将我们的代码编译成二进制可执行文件app RUN go build -o app . # 移动到用于存放生成的二进制文件的 /dist 目录 WORKDIR /dist # 将二进制文件从 /build 目录复制到这里 RUN cp /build/app . # 声明服务端口 EXPOSE 8888 # 启动容器时运行的命令 CMD ["/dist/app"] Dockerfile解析From我们正在使用基础镜像 Env用来设置我们编译阶段需要用的环境变量。 WORKDIR,COPY,RUN这几个命令做的事都写在注释里了,很好理解。 EXPORT,CMD最后,我们声明服务端口,因为我们的应用程序监听的是这个端口并通过这个端口对外提供服务。并且我们还定义了在我们运行镜像的时候默认执行的命令 2.4 构建镜像在项目目录下,执行下面的命令创建镜像,并指定镜像名称为 docker build . -t goweb_app 等待构建过程结束,输出如下提示: ...
Successfully built 90d9283286b7
Successfully tagged goweb_app:latest
现在我们已经准备好了镜像,但是目前它什么也没做。我们接下来要做的是运行我们的镜像,以便它能够处理我们的请求。运行中的镜像称为容器。 执行下面的命令来运行镜像: docker run -p 8888:8888 goweb_app 标志位 现在就可以测试下我们的web程序是否工作正常,打开浏览器输入 hello Pythia.com! 三、分阶段构建示例我们的Go程序编译之后会得到一个可执行的二进制文件,其实在最终的镜像中是不需要go编译器的,也就是说我们只需要一个运行最终二进制文件的容器即可。 Docker的最佳实践之一是通过仅保留二进制文件来减小镜像大小,为此,我们将使用一种称为多阶段构建的技术,这意味着我们将通过多个步骤构建镜像。 FROM golang:alpine AS builder # 为我们的镜像设置必要的环境变量 ENV GO111MODULE=on \ CGO_ENABLED=0 \ GOOS=linux \ GOARCH=amd64 # 移动到工作目录:/build WORKDIR /build # 将代码复制到容器中 COPY . . # 将我们的代码编译成二进制可执行文件 app RUN go build -o app . ################### # 接下来创建一个小镜像 ################### FROM scratch # 从builder镜像中把/dist/app 拷贝到当前目录 COPY --from=builder /build/app / # 需要运行的命令 ENTRYPOINT ["/app"] 使用这种技术,我们剥离了使用 四、附带其他文件的部署示例这里以我之前《Go Web视频教程》中的小清单项目为例,项目的Github仓库地址为:https://github.com/Q1mi/bubble。 如果项目中带有静态文件或配置文件,需要将其拷贝到最终的镜像文件中。 我们的bubble项目用到了静态文件和配置文件,具体目录结构如下: bubble ├── README.md ├── bubble ├── conf │ └── config.ini ├── controller │ └── controller.go ├── dao │ └── mysql.go ├── example.png ├── go.mod ├── go.sum ├── main.go ├── models │ └── todo.go ├── routers │ └── routers.go ├── setting │ └── setting.go ├── static │ ├── css │ │ ├── app.8eeeaf31.css │ │ └── chunk-vendors.57db8905.css │ ├── fonts │ │ ├── element-icons.535877f5.woff │ │ └── element-icons.732389de.ttf │ └── js │ ├── app.007f9690.js │ └── chunk-vendors.ddcb6f91.js └── templates ├── favicon.ico └── index.html 我们需要将 FROM golang:alpine AS builder # 为我们的镜像设置必要的环境变量 ENV GO111MODULE=on \ CGO_ENABLED=0 \ GOOS=linux \ GOARCH=amd64 # 移动到工作目录:/build WORKDIR /build # 复制项目中的 go.mod 和 go.sum文件并下载依赖信息 COPY go.mod . COPY go.sum . RUN go mod download # 将代码复制到容器中 COPY . . # 将我们的代码编译成二进制可执行文件 bubble RUN go build -o bubble . ################### # 接下来创建一个小镜像 ################### FROM scratch COPY ./templates /templates COPY ./static /static COPY ./conf /conf # 从builder镜像中把/dist/app 拷贝到当前目录 COPY --from=builder /build/bubble / # 需要运行的命令 ENTRYPOINT ["/bubble", "conf/config.ini"] 简单来说就是多了几步COPY的步骤,大家看一下 Tips: 这里把COPY静态文件的步骤放在上层,把COPY二进制可执行文件放在下层,争取多使用缓存。 4.1 关联其他容器又因为我们的项目中使用了MySQL,我们可以选择使用如下命令启动一个MySQL容器,它的别名为 docker run --name mysql8019 -p 13306:3306 -e MYSQL_ROOT_PASSWORD=root1234 -v /Users/q1mi/docker/mysql:/var/lib/mysql -d mysql:8.0.19 这里需要修改一下我们程序中配置的MySQL的host地址为容器别名,使它们在内部通过别名(此处为mysql8019)联通。 [mysql] user = root password = root1234 host = mysql8019 port = 3306 db = bubble 修改后记得重新构建 docker build . -t bubble_app 我们这里运行 docker run --link=mysql8019:mysql8019 -p 8888:8888 bubble_app 五、Docker Compose模式除了像上面一样使用
使用Compose基本上是一个三步过程:
我们的项目需要两个容器分别运行 # yaml 配置 version: "3.7" services: mysql8019: image: "mysql:8.0.19" ports: - "33061:3306" command: "--default-authentication-plugin=mysql_native_password --init-file /data/application/init.sql" environment: MYSQL_ROOT_PASSWORD: "root1234" MYSQL_DATABASE: "bubble" MYSQL_PASSWORD: "root1234" volumes: - ./init.sql:/data/application/init.sql bubble_app: build: . command: sh -c "./wait-for.sh mysql8019:3306 -- ./bubble ./conf/config.ini" depends_on: - mysql8019 ports: - "8888:8888" 这个 Compose 文件定义了两个服务: bubble_app使用当前目录下的 mysql8019mysql8019 服务使用 Docker Hub 的公共 mysql:8.0.19 镜像,内部端口3306,外部端口33061。 这里需要注意一个问题就是,我们的 # Dockerfile ... # 需要运行的命令(注释掉这一句,因为需要等MySQL启动之后再启动我们的Web程序) # ENTRYPOINT ["/bubble", "conf/config.ini"] 第二个地方是在 command: sh -c "./wait-for.sh mysql8019:3306 -- ./bubble ./conf/config.ini" 当然,因为我们现在要在 FROM golang:alpine AS builder # 为我们的镜像设置必要的环境变量 ENV GO111MODULE=on \ CGO_ENABLED=0 \ GOOS=linux \ GOARCH=amd64 # 移动到工作目录:/build WORKDIR /build # 复制项目中的 go.mod 和 go.sum文件并下载依赖信息 COPY go.mod . COPY go.sum . RUN go mod download # 将代码复制到容器中 COPY . . # 将我们的代码编译成二进制可执行文件 bubble RUN go build -o bubble . ################### # 接下来创建一个小镜像 ################### FROM debian:stretch-slim COPY ./wait-for.sh / COPY ./templates /templates COPY ./static /static COPY ./conf /conf # 从builder镜像中把/dist/app 拷贝到当前目录 COPY --from=builder /build/bubble / RUN set -eux; \ apt-get update; \ apt-get install -y \ --no-install-recommends \ netcat; \ chmod 755 wait-for.sh # 需要运行的命令 # ENTRYPOINT ["/bubble", "conf/config.ini"] 所有的条件都准备就绪后,就可以执行下面的命令跑起来了: docker-compose up 完整版代码示例,请查看我的github仓库:https://github.com/Q1mi/deploy_bubble_using_docker。 总结使用Docker容器能够极大简化我们在配置依赖环境方面的操作,但同时也对我们的技术储备提了更高的要求。对于Docker不管你是熟悉抑或是不熟悉,技术发展的车轮都滚滚向前。 参考链接: 原文链接: https://www.liwenzhou.com/posts/Go/how_to_deploy_go_app_using_docker/ |
请发表评论