前言

Makefile主要出现在c/c++的项目居多,用来管理c/c++的编译依赖。 这里的用法有点非主流的感觉,但是经过本人的实践。用好Makefile可以事半功倍。

一、演示创建一个docker容器的过程

这里只是为了演示工作流程,所以对docker命令的介绍会一带而过。 下面给一个微服务,做个docker镜像。并启动这个容器。

1.准备一个虚拟的服务

  • 编译命令
1
env CGO_ENABLED=0 go build main.go
  • 源码 你可以看到这个虚拟服务只是打印一句话就退出,这个虚拟服务替换成你的业务服务
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
package main

import (
	"fmt"
)

func main() {
	fmt.Printf("vim-go")
}

2.创建docker镜像

alpine 是docker里面比较mini的镜像,大约4MB左右,特别适合把服务拆得很散。 ubuntu镜像占100-200MB的样子。来个7-8个微服务。啥也不干,第一次pull 1G空间都没了。 如果docker registry和项目开发不在一个网段,中间使用外网通信。上传,下载的时间也相当可观。 使用alpine大约可以节省10x等待时间。

1
2
3
4
5
6
7
8
FROM alpine:3.7

RUN mkdir -p /opt/service
COPY ./main /opt/service
COPY ./start.sh /opt/service
WORKDIR /opt/service

CMD ["./start.sh"]
  • FROM 使用alpine:3.7基础镜像构建自己的镜像
  • RUN 运行shell命令
  • COPY 本地文件拷贝到镜像里面
  • WORKDIR 设置镜像工作目录,下面的CMD命令都没有使用绝对路径/opt/service就可以执行start.sh命令, 就是这个指令的作用
  • CMD 类似编程语言的main函数。入口指令

3. start.sh内容

使用start.sh包裹服务启动脚本,是为了把经常变的部分放到start.sh里面。不变的部分放到Dockerfile里面维护。 debug的时候,就发现这个方式比CMD直接放启动命令好多了。

1
2
./main

4.编译容器

1
sudo docker build -t demo:v1 .

5.运行容器

1
sudo docker run --net=host --name demo_v1 -d demo:v1

6.删除容器

没问题,就不同删除容器

1
sudo docker rm demo_v1

7.删除镜像

没问题,就不同删除镜像

1
sudo docker rmi demo:v1

二、优化工作流

如果上面的脚本一遍过,基本也不需要优化工作流,如果一次不成功,遇到疑难杂症。来来回回几次(删除,创建,运行)。 就要吐了。 遇到这种情况,大家第一个反应是使用bash优化流程。先来个switch case骨架代码,他接受不同参数,运行不同子命令

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
# 文件名 workflow.sh
#!/bin/sh

case "$1" in
    "build" )
        echo $1
        ;;

    "reset.docker" )
        echo $1
        ;;

    "build.docker" )
        echo $1
        ;;

    "run.docker" )
        echo $1
        ;;

esac

  • 运行
1
sh  workflow.sh build

好了,把上面的docker命令,移动到 workflow.sh脚步里面,加速工作流

三、优化工作流

如果你对第二步已经满足就不用看第三步。第二步要写switch case骨架代码。有没有一种方式,原生支持多入口子命令执行。答:Makefile ok。现在使用Makefile重构上面的shell脚本。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
export GOPROXY=https://goproxy.cn
export GO111MODULE=on

# 模拟-编译go服务
build:
    echo "这里放编译命令,同理下面也是"

# 清理,重新创建
reset.docker: clean.docker build.docker

# docker build list clean
build.docker:

# 运行
run.docker:

# 删除容器和镜像
clean.docker: clean.container clean.images 

# 删除镜像
clean.images:

# 删除容器
clean.container:
  • 运行
1
make -f workflow.make build

Makefile不仅完成第二步内容,还支持命令组合。比如上面的reset.docker命令,就是先执行clean.docker后执行build.docker 当然,这里为了演示使用workflow.make文件名,如果使用默认Makefile文件名是不需要make -f指定Makefile脚本文件,直接make build就可以。

github 源码位置

https://github.com/guonaihong/go-example/tree/main/docker-alpine