应用程序的日志输出到文件.
但是也为了能用docker logs
, kubectl logs
等形式能查看标准输出, 所以用了tee
这个命令.
为了说明问题, 先列出所需要的文件:
main.go (模拟应用程序)
package main
import (
"fmt"
"time"
)
func main() {
for {
fmt.Println("now is:", time.Now().Format("2006-01-02 15:04:05"))
time.Sleep(time.Second)
}
}
Dockerfile_pipe (使用pipe形式来实现同时输出到文件和标准输出)
FROM alpine
COPY ./main ./
RUN chmod 0755 ./main && echo "exec ./main 2>&1 | tee -a /tmp/a.log" > ./start.sh
ENTRYPOINT ["/bin/sh", "./start.sh"]
Dockerfile_exec (使用exec形式来实现同时输出到文件和标准输出)
FROM alpine
# use aliyun source, Optional
RUN ver=$(grep -E -o '[0-9]+\.[0-9]+$' /etc/issue); \
printf "http://mirrors.aliyun.com/alpine/v%s/main/\nhttp://mirrors.aliyun.com/alpine/v%s/community/" $ver $ver >/etc/apk/repositories
RUN apk add --no-cache bash
COPY ./main ./
RUN chmod 0755 ./main && echo "exec 8> >(tee -a /tmp/a.log); exec ./main >&8 2>&1" > ./start.sh
ENTRYPOINT ["/bin/bash", "./start.sh"]
上述exec 8> >(tee -a /tmp/a.log); exec ./main >&8 2>&1的意思是:
>(tee -a /tmp/a.log)
:>(...)
: 启动进程(tee -a /tmp/a.log)并返回一个代表了此进程标准输入的文件exec 8>
新建一个文件描述符8(只能写入), 并与上述的文件关联exec ./main
启动main, 并替换当前进程体(一般是替换当前shell)
Makefile
$ cat Makefile
#
# Makefile
#
imageUrlPipe="test-pipe:1.0"
imageUrlExec="test-exec:1.0"
all: image-exec image-pipe
compile:
go build -ldflags='-s -w' -o main main.go
image-pipe: compile
docker build -t $(imageUrlPipe) -f Dockerfile_pipe .
image-exec: compile
docker build -t $(imageUrlExec) -f Dockerfile_exec .
.PHONY: clean
clean:
rm -f main; \
docker rmi -f $(imageUrlExec) $(imageUrlPipe);