1. 原理解析

1.1 构建包含 reflex 的镜像

然后,克隆我放在 Github 上的项目:

[root@CentOS ~]# git clone https://github.com/wangy8961/go-docker-dev.git
[root@CentOS ~]# cd go-docker-dev/
Golang
reflex.gogo.modreflexreflex.confsh -c /usr/src/build.sh
-r '(\.go$|go\.mod)' -s -- sh -c /usr/src/build.sh
build.sh/app
#!/bin/bash

cd /app
# 编译,GO_BUILD_FLAGS 是可选的环境变量值
go build -o app ${GO_BUILD_FLAGS}
# 运行,APP_RUN_FLAGS 是可选的环境变量值
./app ${APP_RUN_FLAGS}
reflex -c /usr/src/reflex.confDockerfile
FROM golang:1.12.5-stretch

# 设置代理,因为后续 go get github.com/cespare/reflex 会下载依赖 golang.org/x/sys/unix 等
ENV HTTP_PROXY='socks5://127.0.0.1:1080'
ENV HTTPS_PROXY='socks5://127.0.0.1:1080'
# 安装 reflex 包
RUN go get github.com/cespare/reflex
# 复制 reflex 的配置文件到容器中的根目录下
COPY reflex.conf /usr/src
COPY build.sh /usr/src
# 设置容器内的工作目录,用于 RUN, CMD, ENTRYPOINT, COPY, ADD 等指令
WORKDIR /app
# 容器启动时,运行 reflex -c /usr/src/reflex.conf
# 由于工作目录已切换到 /app,所以 reflex 会监控 /app 目录下的 .go 或 go.mod 文件的变化
ENTRYPOINT ["reflex", "-c", "/usr/src/reflex.conf"]
1080--network host
[root@CentOS go-docker-dev]# docker build --network host -t go-docker-dev:latest .
Sending build context to Docker daemon  75.26kB
Step 1/8 : FROM golang:1.12.5-stretch
 ---> 7ced090ee82e
Step 2/8 : ENV HTTP_PROXY='socks5://127.0.0.1:1080'
 ---> Running in 253791251a63
Removing intermediate container 253791251a63
 ---> c786afb6d6db
Step 3/8 : ENV HTTPS_PROXY='socks5://127.0.0.1:1080'
 ---> Running in cfca59a05f33
Removing intermediate container cfca59a05f33
 ---> 6aef3386ba42
Step 4/8 : RUN go get github.com/cespare/reflex
 ---> Running in fe62a278b71c
Removing intermediate container fe62a278b71c
 ---> 0719584291f8
Step 5/8 : COPY reflex.conf /usr/src
 ---> ab3a4f0441e9
Step 6/8 : COPY build.sh /usr/src
 ---> 9fd7880705d3
Step 7/8 : WORKDIR /app
 ---> Running in 505b279617b5
Removing intermediate container 505b279617b5
 ---> 5e36e28a80b5
Step 8/8 : ENTRYPOINT ["reflex", "-c", "/usr/src/reflex.conf"]
 ---> Running in dab2661248e8
Removing intermediate container dab2661248e8
 ---> 4b966b116294
Successfully built 4b966b116294
Successfully tagged go-docker-dev:latest

1.2 新建 Golang 项目

Go Modulesgo-example
[root@CentOS go-docker-dev]# mkdir go-example
[root@CentOS go-docker-dev]# cd go-example/
[root@CentOS go-example]# go mod init go-example
go: creating new go.mod: module go-example
[root@CentOS go-example]# cat go.mod 
module go-example

go 1.12
VSCodenet/httpgo-docker-dev/go-example/main.go
package main

import (
    "flag"
    "fmt"
    "log"
    "net/http"
)

func main() {
    port := flag.Int("port", 50051, "the port to serve on")
    flag.Parse()

    http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
        fmt.Fprintf(w, "Hello, you've requested: %s\n", r.URL.Path)
    })

    err := http.ListenAndServe(fmt.Sprintf(":%d", *port), nil)
    if err != nil {
        log.Fatalf("failed to listen: %v", err)
    }
    fmt.Printf("server listening on port: %v\n", fmt.Sprintf(":%d", *port))
}
-port 80

启动容器:

[root@CentOS go-docker-dev]# docker run -d \
  --name go-example \
  -e "APP_RUN_FLAGS=-port 80" \
  -p 80:80 \
  --rm \
  -v $PWD/go-example:/app \
  go-docker-dev:latest

b78cfaf9eac6147ca9cf6c84eb2355057a1d1323a086b2a3fd987495e44edc63

[root@CentOS go-docker-dev]# docker ps
CONTAINER ID        IMAGE                  COMMAND                  CREATED             STATUS              PORTS                NAMES
b78cfaf9eac6        go-docker-dev:latest   "reflex -c /usr/src/…"   4 seconds ago       Up 3 seconds        0.0.0.0:80->80/tcp   go-example

你可以进去容器内部看看它启动了哪些进程:

[root@CentOS go-docker-dev]# docker exec -it go-example /bin/bash
root@b78cfaf9eac6:/app# ps -ef
UID        PID  PPID  C STIME TTY          TIME CMD
root         1     0  0 06:48 ?        00:00:00 reflex -c /usr/src/reflex.conf
root        17     1  0 06:48 pts/0    00:00:00 sh -c /usr/src/build.sh
root        18    17  0 06:48 pts/0    00:00:00 /bin/bash /usr/src/build.sh
root       125    18  0 06:48 pts/0    00:00:00 ./app -port 80  # 我们通过环境变量和 build.sh 来指定命令行参数
root       131     0  4 06:51 pts/1    00:00:00 /bin/bash
root       138   131  0 06:51 pts/1    00:00:00 ps -ef
root@b78cfaf9eac6:/app# exit
exit
192.168.40.128

reflex 01

main.go
func main() {
    ...
    fs := http.FileServer(http.Dir("static/"))
    http.Handle("/static/", http.StripPrefix("/static/", fs))
    ...
}
reflexgo-docker-dev/go-example/static/madmalls.jpg

然后,你再通过浏览器访问:

reflex 02

2. 如何快速使用

你只需要先安装 Dokcer 和 Docker Compose,并克隆我放在 Github 上的项目:

[root@CentOS ~]# git clone https://github.com/wangy8961/go-docker-dev.git
[root@CentOS ~]# cd go-docker-dev/
docker-compose.ymlportsvolumes/app/appbuild.sh
version: "3.7"
services:

  go-example:
    # building image from ./Dockerfile, and change network mode to 'host', because 'go get' need proxy in Dockerfile
    build:
      context: .
      network: host
    # specify the image name after builded
    image: go-docker-dev:latest
    ports:
      - "80:80"
    # go-example is your Golang project name,
    # don't change the target path '/app', because 'reflex' will go to there and then run 'go build .'
    volumes:
      - "$PWD/go-example:/app"
    # specify container name
    container_name: go-example
    # environment file
    env_file:
      - .env
go-docker-dev/go-example
.env
GO_BUILD_FLAGS=-race
APP_RUN_FLAGS=-port 80
Docker Compose127.0.0.1:1080
[root@CentOS go-docker-dev]# docker-compose up
Building go-example
Step 1/8 : FROM golang:1.12.5-stretch
 ---> 7ced090ee82e
Step 2/8 : ENV HTTP_PROXY='socks5://127.0.0.1:1080'
 ---> Running in c90a5c67b8a3
Removing intermediate container c90a5c67b8a3
 ---> b4a255b862a0
Step 3/8 : ENV HTTPS_PROXY='socks5://127.0.0.1:1080'
 ---> Running in e186621097a4
Removing intermediate container e186621097a4
 ---> c52fcc75f69c
Step 4/8 : RUN go get github.com/cespare/reflex
 ---> Running in 413f495624b7
Removing intermediate container 413f495624b7
 ---> ce99643777f7
Step 5/8 : COPY reflex.conf /usr/src
 ---> ba5af0210f69
Step 6/8 : COPY build.sh /usr/src
 ---> a13e467a9ffd
Step 7/8 : WORKDIR /app
 ---> Running in f372bcfd30f3
Removing intermediate container f372bcfd30f3
 ---> 6b50f6a9d219
Step 8/8 : ENTRYPOINT ["reflex", "-c", "/usr/src/reflex.conf"]
 ---> Running in ae580ee69746
Removing intermediate container ae580ee69746
 ---> 33efe4b5ac0f

Successfully built 33efe4b5ac0f
Successfully tagged go-docker-dev:latest
WARNING: Image for service go-example was built because it did not already exist. To rebuild this image you must use `docker-compose build` or `docker-compose up --bui
ld`.Creating go-example ... done
Attaching to go-example
go-example    | [00] Starting service
docker-compose up -d