之前项目开发一直是在1024code上面进行,1024code还是非常方便,集成了git、数据库(包括MySQL,Redis,PostgreSQL)、可远程访问的服务器地址、以及一个可以多人在线协作的网页IDE编辑器、等等等等方便快捷的功能。
当然,这个IDE肯定不如GoLand或者VS Code那么强大,对于像我这样的Golang新手来说还是有点不太友好。
一番挣扎之后,还是决定尝试利用Docker搭建一个本地的测试环境。得益于Docker优秀的跨平台无障碍的特性,如果我能够成功地搭建起这个测试环境,那么我的小伙伴们也可以直接使用了。
写个笔记记录一下搭建和测试的过程。
前置工作
前置工作当然是确保本地已经安装好了Docker。
Windows: docs.docker.com/desktop/ins…
MacOS: docs.docker.com/desktop/ins…
环境搭建
想法是用docker-compose部署两个服务:db和backend。分别对应MySQL数据库和我们的Golang后端的项目代码。db服务的容器可以直接从Docker Hub的官方镜像拉取,而backend服务对应的容器则需要我们自己写一个Dockerfile来构建它。
配置docker-compose.yaml
在项目的根目录新建一个文件:docker-compose.yaml。
version: '3'
services:
db:
image: mysql:latest
environment:
MYSQL_ROOT_PASSWORD: rootpassword
MYSQL_DATABASE: mysql
MYSQL_USER: user
MYSQL_PASSWORD: password
MYSQL_TEST_DATABASE: gotest
volumes:
- db_data:/var/lib/mysql
ports:
- "3306:3306"
command: '--default-authentication-plugin=mysql_native_password'
backend:
build: .
volumes:
- .:/app
ports:
- "8080:8080"
depends_on:
- db
environment:
MYSQL_USER: user
MYSQL_PASSWORD: password
MYSQL_HOST: db
MYSQL_PORT: 3306
command: ["/app/wait-for-it.sh", "db:3306", "--", "go", "run", "."]
volumes:
db_data:
可以看到我们在配置文件中定义了上面所说的两个服务db和backend。
我们来简单解释一下。
db 服务
从官方的MySQL镜像拉取,设置了几个环境变量:MYSQL_ROOT_PASSWORD、MYSQL_DATABASE、MYSQL_USER、MYSQL_PASSWORD、MYSQL_TEST_DATABASE。用来在容器中创建对应的数据库、用户、密码等等。
然后我们定义了一个volume - db_data,用于持久存储数据库数据。这样即使我们删除了容器,数据也不会丢失。
我们将容器内部的3306端口映射出来,这样我们的后端服务才能访问到数据库。
backend 服务
build . 命令告诉Docker compose去当前目前下查找Dockerfile文件来构建容器。
同时我们也做了一个卷的映射,将当前目录映射到容器内的app文件夹,这样我们在本地开发的时候,任何修改都会同步到容器内部,避免了每次做完一点点修改都要重新build docker compose。
类似地,我们将容器内部的8080端口映射到外部,这样我们才能访问后端服务器。
我们声明了depends_on,告诉docker compose要在backend服务启动之前启动db服务。当然后来我们发现这样也不能确保db服务就能在backend服务启动之前完全初始化,等一下会将解决办法。
我们给backend服务也设置了一些环境变量,用来给Golang程序获取数据库的信息。
最后我们定义了两个启动命令:
/app/wait-for-it.sh db:3306 --,因为刚才提到了我们不能保证db服务就能在backend服务启动之前完全初始化,这种情况下我们的后端服务去连接数据库就会报错,然后backend服务就退出了。因此我们利用了一个程序wait-for-it(开源仓库github.com/vishnubob/w…- 等数据库服务完全初始化后,我们就用命令
go run .来启动后端服务。
Dockerfile
以上就是我们docker compose配置文件的大致流程。现在我们来看一下Dockerfile。
FROM golang:1.20
WORKDIR /app
COPY wait-for-it.sh /app/wait-for-it.sh
RUN chmod +x /app/wait-for-it.sh
COPY . .
CMD ["go", "run", "."]
这个容器基于golang 1.20的镜像,默认的工作路径是/app。
然后我们把wait-for-it.sh文件拷贝到工作路径下,并且在容器内赋予它可执行的权限。
然后把当前目录(项目根目录)复制到容器内的默认路径,也就是刚才声明的/app下(不确定这步是否必要,因为我们之前在docker compose里面已经映射了这两个目录,但是至少经过测试是可以达到预期的运行效果的)。
最后定义容器的初始运行命令为go run .
启动docker compose并测试
命令:
docker compose up
可选参数:
-d: 在后台运行,不在前台输出运行日志 --build: 强制重新构建容器,不加这个参数就是默认按照上次构建的容器来运行。首次启动的时候会自动构建。
如果一切正常,就可以看到类似这样的命令行输出:
>docker-compose up
[+] Running 2/0
✔ Container dousheng-db-1 Created 0.0s
✔ Container dousheng-backend-1 Created 0.0s
Attaching to dousheng-backend-1, dousheng-db-1
然后我们就可以进行API的测试了。我一般用两种测试方式。
Postman
用Postman(或者类似的API测试工具)发送HTTP请求到我们的服务器,这里的基础URL就填http://locahost:8080就好了。
比如我尝试发送一个获取视频流的请求:http://locahost:8080/douyin/feed/?latest_time=1693106942567
得到:
dousheng-backend-1 | [GIN-debug] redirecting request 301: /douyin/feed/ --> /douyin/feed/?latest_time=1693106942567
dousheng-backend-1 | [GIN] 2023/08/27 - 04:00:33 | 200 | 1.119112ms | 172.19.0.1 | GET "/douyin/feed/?latest_time=1693106942567"
抖声APP
因为我们希望最终我们的后端服务器可以正确的处理来自抖声APP的请求,所以使用它来测试我们的后端服务器也是必不可少的。
如果是用安卓手机的同学,可以直接在上面安装官方给的抖声APP的apk包。这种情况下我们要确保我们本机的8080端口是开放给局域网的其它设备的,然后找到我们本机在局域网里的IP地址。假设我们的IP地址是192.168.0.2,那么就在抖声APP的“高级设置”(双击右下角的“我”呼出)中填写BaseUrl为http://192.168.0.2:8080/。然后就可以正常访问我们的后端了。
如果是非安卓手机用户,或者说觉得开放本地端口的操作比较麻烦,也可以选择在本地电脑上装一个安卓模拟器,在那里面安装抖声APP。这种情况下我们的电脑跟安卓模拟器组成的网络下,我们的电脑的IP地址是什么。Windows电脑用ipconfig命令,MacOS用ip addr show命令。类似地,假设找到的IP地址是172.19.64.1,就在BaseUrl中填写http://172.19.64.1:8080/
后续开发
在后续的开发过程中,每当我们想要测试一下刚才新增的代码改动,只需要先将docker compose停止:
docker compose down
然后再重新运行:
docker compose up
这个过程通常就几秒钟,不用每次都重复build,非常方便。