golang程序我们一般是先编译好可执行文件,然后发布出去运行,所以在创建docker镜像的时候,我们也使用这种方式,所以golang程序使用容器来运行实在使太方便了。
common项目是使用gin写的API接口服务,配合endless实现了 graceful restart。
目录结构如下:
编译
go build common.go
启动命令,前台运行
./common serve
启动命令,后台运行
./common serve -d
或者
/bin/man start
平滑重启命令
/bin/man restart
默认情况下,我们的编译 go build xxx 是通过动态链接的方式去调用其他依赖的,生成的可执行文件如果放到别的地方运行的话实际上还是需要系统来提供这些依赖。否则无法运行,所以使用静态链接的方式来编译,这样编译的文件会稍微大一些,但是几乎不会依赖外部环境了。
静态编译方式:
CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo common.go
CGO_ENABLED=0 ,关闭cgo
alpinescratch
如果基础镜像不存在,会从远程下载 docker.io/library/alpine 。
Dockerfile文件内容
FROM alpine
ADD common /data/www/
ADD conf/app.ini /data/www/conf/
ADD bin/man /data/www/bin/
EXPOSE 8001/tcp
WORKDIR /data/www
CMD cd /data/www/ && ./common serve
容器中服务的启动不要使用daemon方式,因此不加 -d 参数。
创建镜像
docker build -t common .
docker images
启动容器
docker run --name common --network host -d common
或者
docker run --name common -p 8001:8001 -d common
docker ps
netstat -lntp
测试
curl http://localhost:8001/common/Stats
如果想进入容器,使用如下命令
docker exec -it common sh
关于前台运行 or 后台运行的问题
容器中要求 pid=1 的程序必须是前台运行的,否则容器立即退出。
具体参考 https://blog.csdn.net/raoxiaoya/article/details/109194514
然而 endless 的 graceful restart 会启动新的进程来提供服务,在试验过程中的确发现容器立即就退出了,针对这个情况可以写一个几乎不消耗性能的程序来作为pid=1,或者使用 top 命令。
于是 Dockerfile 中的 CMD 要改成:
CMD cd /data/www/ && ./common serve -d && top
关于服务的热更新
docker cp common common:/data/wwwdocker exec -it common sh bin/man restart
注意
最后注意一点,在查到进程Id的时候,id所在的位置不一样。
在宿主机上
ps -ef |grep 'common serve' |grep -v grep
root 15286 1 0 Sep28 ? 00:34:57 ./voteapi serve
ps -ef |grep 'common serve' |grep -v grep | awk '{print $2}'
15286
但是在容器内部
ps -ef |grep 'common serve' |grep -v grep
1 root 0:00 ./common serve
ps -ef |grep 'common serve' |grep -v grep | awk '{print $1}'
1
bin/man
容器内部的 kill 命令
kill -l
1) HUP
2) INT
3) QUIT
4) ILL
5) TRAP
6) ABRT
7) BUS
8) FPE
9) KILL
10) USR1
11) SEGV
12) USR2
13) PIPE
14) ALRM
15) TERM
16) STKFLT
17) CHLD
18) CONT
19) STOP
20) TSTP
21) TTIN
22) TTOU
23) URG
24) XCPU
25) XFSZ
26) VTALRM
27) PROF
28) WINCH
29) POLL
30) PWR
31) SYS
35) RTMIN
64) RTMAX
但是
kill -HUP 41
或者
kill -SIGHUP 41
都可以