写了个Go程序,发给同事却跑不起来——这种事,每个程序员都经历过。
问题往往不是代码错了,而是环境不对。对方没装Go,或者版本不同,或者依赖库缺了某个版本。你这边跑得欢,他那边报错一堆。
![]()
Docker就是来解决这个尴尬的。它把代码和运行环境打包成一个"盒子",谁拿到都能原样运行。本文用一个Go应用做案例,手把手教你从单机容器到多容器编排的完整流程。
先理解这个"盒子"是什么
想象一个密封的盒子:里面装着你的代码、Go语言运行时、所有依赖包,甚至操作系统层面的配置。
别人不需要在自己的电脑上装任何东西,打开盒子就能跑。而且无论谁打开,跑出来的结果一模一样。
在Docker的术语里,这个盒子叫镜像(image),打开后的运行状态叫容器(container)。
镜像是个只读的模板,容器则是镜像的实时实例。你可以从一个镜像启动无数个容器,就像用同一份安装盘装出多台配置相同的电脑。
第一步:写个能跑的Go应用
我们从一个最简单的HTTP服务开始。这个服务连上MySQL数据库,对外暴露几个REST接口。
代码结构很常规:main.go里启动服务器,handlers处理请求,models定义数据模型。关键是用标准库database/sql配合go-sql-driver/mysql驱动。
本地跑通后,问题来了:怎么把这个服务连带着MySQL一起打包?数据库也是环境的一部分,总不能让对方自己装MySQL再配表结构吧。
第二步:用Dockerfile造盒子
Dockerfile是一份"造盒说明书",告诉Docker怎么一步步构建镜像。
我们采用多阶段构建(multi-stage build),这是Go容器化的最佳实践。第一阶段用golang:1.19镜像编译出二进制文件,第二阶段用更小的alpine镜像只保留编译结果。
这样最终镜像体积能从几百MB压缩到十几MB。Go编译成静态链接的二进制文件,天生适合这种瘦身操作。
关键指令就这几行:FROM选基础镜像,WORKDIR设工作目录,COPY把代码拷进去,RUN执行编译,EXPOSE声明端口,CMD指定启动命令。
注意GOOS=linux GOARCH=amd64的交叉编译参数,确保在Mac或Windows上编译出来的二进制能在Linux容器里跑。
第三步:一台机器跑多个盒子
单个容器还不够。真实场景里,Go服务依赖MySQL,可能还需要phpMyAdmin看数据。三个服务怎么协同?
Docker Compose登场。它用一个YAML文件定义多容器应用,一键启动整套环境。
docker-compose.yml里我们定义三个服务:app(Go应用)、db(MySQL)、phpmyadmin(数据库管理界面)。
每个服务指定镜像来源、端口映射、环境变量、卷挂载。关键是depends_on字段,确保MySQL先启动,Go应用后启动,避免连接报错。
网络配置让三个容器互相可见。Docker Compose自动创建隔离的虚拟网络,服务名就是主机名,Go代码里写"db:3306"就能连上MySQL。
第四步:跑起来看看
命令行里docker-compose up,三个容器依次启动。终端里能看到彩色日志输出,哪个服务报了什么错一目了然。
测试一下:curl http://localhost:8080/users 能拿到数据,打开 http://localhost:8081 是phpMyAdmin登录页。整套环境在一台机器上跑起来了,和本地开发完全一致。
关掉也简单,docker-compose down一键清理,不留垃圾。
这到底改变了什么
以前部署一个Go+MySQL的应用,要写安装文档、配环境变量、处理版本冲突。现在一个docker-compose.yml文件,新人第一天就能跑起来。
更隐蔽的好处是环境一致性。开发、测试、生产用同一个镜像,"我本地没问题"这种对话彻底消失。
对25-40岁的技术从业者来说,这省下的不是装环境的那几小时,而是排查环境差异的整天整天。把时间花在代码上,而不是和机器较劲。
特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。
Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.