作者 青鸟

记录一次关于docker部署时候的debug

问题

昨天的时候针对学校的统一认证做了一个简单的逆向,并打算将逆向结果用于校园论坛的认证。但是在将逆向结果打成docker部署后,访问校园认证系统的时候出现了tls:x509 certificate signed by unknown authority的错误。经过一番debug确定了问题出在了ssl证书上,导致了容器内部访问https出错。现对问题做一个具体的分析。

go语言天生适合运行在docker中,这得益于go的静态编译可以将go项目打包成一个二进制文件而无需依赖配置,可以完全独立运行在容器中且只需要最小的scratch的支持。关于docker部署的流程就不在此赘述了,详情可以见之前的博客。但是当我们对外访问的使用https的时候就会出现tls:x509 certificate signed by unknown authority的错误。

原因很简单,众所周知,https是基于ca证书的,但是我们打包成容器时候使用的是scratch,这就导致了ca证书的缺失,同时go的基础镜像于是基于scratch的,这也导致了使用golang作为基础镜像会缺少对与ssl的支持。而其他一些语言基于linux镜像之上会安装了ca-certificates这个应用,于是就实现了对ssl的支持。

在debug的时候使用了curl这个工具,我们却可以在容器中得到https的反馈结果,这是由于curl是ca-certificates的上层应用,curl在安装的同时,openssl会去安装ca-certificates这个应用。

解决方案

第一种就是使用ubuntu镜像,并且在docker build 的时候安装ca-certificates,在dockerfile中写入apt install ca-certificates即可。

1
2
3
4
5
6
7
FROM ubuntu
MAINTAINER cbluebird
WORKDIR /app
COPY hello /app
EXPOSE 6060
RUN apt-get install ca-certificates
CMD ["./hello"]

第二种方案是将证书挂载到docker中即可。我们使用wget https://curl.haxx.se/ca/cacert.pem下载一个官方证书。在linux中一般的证书默认在/etc/ssl/certs目录下。直接add进来就可以。

1
2
3
4
5
6
7
FROM scratch
MAINTAINER cbluebird
ADD cacert.pem /etc/ssl/certs/
WORKDIR /app
COPY hello /app
EXPOSE 6060
CMD ["./hello"]

题外话

在ubuntu中安装docker-compose还是挺痛苦的,使用apt-get安装的版本较低,按照网上的curl的话总是不可执行并且时间还受到资源限制。经过一番试验,建议在官方的release中找到对应的版本,使用sftp上传到usr/local/bin中,给予执行权限即可。这样子方便又高效

参考文章: