最近写了几个推特API的接口,在本机(mac)测试的时候好好的 部署到服务器上的时候发现不能用了 报错:
{
"code": 500,
"msg": "err : Get \"https://api.twitter.com/2/users/by/username/StarGate_Dev\": x509: certificate signed by unknown authority"
}
本来还以为是推特API没加服务器地址为后台回调地址的事儿 但是加了以后也不能用 仔细思考一下 本地测试的时候后台也没加我的这个局域网的ip为回调 为什么就能用呢
所以不是回调的事儿
在网上找了一番 发现这个错误还挺常见 就是
我们一般用docker或者 docker-compose 部署服务的时候 ,选用的要挂载的基础linux(centos或者ubuntu等待)镜像 ,默认是不带 ca-certificates 根证书的,导致无法识别外部 https 携带的数字证书。
知道了原因就好办了
如果你是用生成docker镜像的方式去部署呢 那么 要在构建 docker 镜像的时候把 ca-certificates 根证书给装上,这样就能识别来自外部 https 的数字证书了。
这里以utuntu基础镜像为例,apt-get是utuntu的下载命令
在编辑 Dockerfile 的时候加入以下命令即可:
RUN apt-get -qq update \
&& apt-get -qq install -y --no-install-recommends ca-certificates curl
注意如果是在使用 golang:alpine 作为基础镜像时,你无法使用 apt 命令,因为 Alpine Linux 发行版使用的是 apk 包管理器而不是 apt
RUN apk update && \
apk add --no-cache ca-certificates
如果你是用docker-compose 挂载二进制文件的方式部署 那么就进入docker-compose 给你起的容器内 安装根证书
先进入容器
$ docker exec -it '容器ID或容器名称' /bin/bash
再执行以下命令
apt-get -qq update
apt-get -qq install -y --no-install-recommends ca-certificates curl
最后退出restart 服务即可。这是你可以进入容器的情况,但是有时候代码一开跑就会遇到这个问题,容器压根起不来 你也进不去容器里 如果你也是这种情况,可以看最下边的第四种方案 通过volume的方式解决。
[root@ecs-51ff home]# docker exec -it 76094 /bin/bash
root@76094de917e2:/stargate# ls
dev.yaml stargate stargate11-25 stargate11-30
root@76094de917e2:/stargate# cd ..
root@76094de917e2:/# ls
bin boot dev etc home lib lib64 media mnt opt proc root run sbin srv stargate sys tmp usr var
root@76094de917e2:/# apt-get -qq update
root@76094de917e2:/# apt-get -qq install -y --no-install-recommends ca-certificates curl
debconf: delaying package configuration, since apt-utils is not installed
Selecting previously unselected package libssl1.1:amd64.
(Reading database ... 4051 files and directories currently installed.)
。。。。。。。。省略。。。。。。
Updating certificates in /etc/ssl/certs...
127 added, 0 removed; done.
。。。。。。。。省略。。。。。。
Processing triggers for libc-bin (2.27-3ubuntu1.6) ...
Processing triggers for ca-certificates (20211016~18.04.1) ...
Updating certificates in /etc/ssl/certs...
0 added, 0 removed; done.
Running hooks in /etc/ca-certificates/update.d...
done.
root@76094de917e2:/# exit
[root@ecs-51ff home]# docker-compose restart stargate
Restarting home_stargate_1 ... done
这个时候再去访问服务器的服务 就可以正常使用啦
docker-compose方式的这里要小心 如果你把服务down掉 也就是这个容器会被清理
所以你再次up起来的容器 是一个全新的容器 需要再次根证书配置噢
参考:https://www.jianshu.com/p/97471c082b2f
2024-04-26更新
解决x509问题的几种思路 :
一是 自己制作镜像 将本地的根证书复制到镜像中
# 使用基于 Ubuntu 18.04 的镜像
FROM ubuntu:18.04
# 将本地的根证书复制到镜像中
COPY ./ca/certs/ca_root.crt /usr/local/share/ca-certificates/ca_root.crt
# 更新系统证书
RUN update-ca-certificates
# 可选:设置工作目录
WORKDIR /app
# 可选:拷贝其他文件到镜像中
# COPY . /app
# 可选:设置环境变量等
# 启动时执行的命令(如果需要)
# CMD ["/app/startup.sh"]
二是 自己制作镜像 制作过程中将证书相关的下载好 ,比如可以制作一个基于ubuntu:18.04的镜像 然后拿来当compose 的ubuntu基础镜像用。
三是 自己制作镜像 同时把业务代码一块打进去
#FROM ubuntu:latest
#LABEL authors="hanpeng"
#
#ENTRYPOINT ["top", "-b"]
FROM golang:alpine AS builder
#FROM golang:1.16-alpine3.12 AS builder
# 为我们的镜像设置必要的环境变量
ENV GO111MODULE=on \
GOPROXY=https://goproxy.cn,direct \
CGO_ENABLED=0 \
GOOS=linux \
GOARCH=amd64
# 移动到工作目录:/build
WORKDIR /build
# 将代码复制到容器中
COPY . .
# 复制项目中的 go.mod 和 go.sum文件并下载依赖信息
#COPY go.mod .
#COPY go.sum .
RUN go mod download
# 下载根证书 解决x509: certificate signed by unknown authority问题
# 在使用 golang:alpine 作为基础镜像时,你无法使用 apt 命令,因为 Alpine Linux 发行版使用的是 apk 包管理器而不是 apt。
# 在 Dockerfile 中,合并多个命令为单个 RUN 命令,这样可以减少镜像中的层次数
RUN apk update && \
apk add --no-cache ca-certificates
# 将我们的代码编译成二进制可执行文件app
RUN go build -o ant_service .
###################
# 接下来创建一个小镜像
###################
#FROM shinsenter/scratch
FROM scratch
ENV GOARCH=amd64
# 从builder镜像中把/dist/app 拷贝到当前目录
COPY --from=builder /build/ant_service /
## 移动到用于存放生成的二进制文件的 /dist 目录
#WORKDIR /dist
## 将二进制文件从 /build 目录复制到这里
#RUN cp /build/ant_service .
COPY ./etc ./etc
# 声明服务端口
EXPOSE 13005
# 需要运行的命令。Entrypoint指令用于设定容器启动时第一个运行的命令及其参数,后面的值就是参数
ENTRYPOINT ["/ant_service", "/etc/antservice-api.yaml"]
# 启动容器时运行的命令
#CMD ["/dist/app"]
四是 针对compose的,可以通过 将宿主机的ca证书配置 拷贝到指定目录 然后通过volumes的方式 加载到容器的/etc/ssl/certs/下 解决x509问题。注意⚠️ 一定要定位到单个.crt文件 才可以。整个文件的 我这里失败了
version: '3.5'
services:
fugu:
# image: ant_service:beta
image: ubuntu:18.04
restart: always
working_dir: /ant
volumes:
- ./ant:/ant
# ca证书配置 将宿主机的拷贝到指定目录 然后通过volumes的方式 加载到容器的/etc/ssl/certs/下 解决x509问题
- ./ca/certs/ca-bundle.crt:/etc/ssl/certs/ca-bundler.crt
ports:
- 13006:13005
command: ./qg-blockchain-sdk-linux
networks:
compose_network:
ipv4_address: ${BCNET_PREFIX}.11
redis:
image: redis:latest
restart: always
command: redis-server --appendonly yes
volumes:
- './redis/data:/data'
ports:
- 16380:6379
networks:
compose_network:
ipv4_address: ${BCNET_PREFIX}.12
networks:
compose_network:
external: true
name: ${BCNET}
五是 针对compose的,可以通过 command命令来进行ca的配置下载
但是这里我试的失败了 这里仅提供思路
version: '3.5'
services:
ant:
# image: ant_service:beta
image: ubuntu:18.04
restart: always
working_dir: /ant
volumes:
- ./ant:/ant
# ca证书配置 将宿主机的拷贝到指定目录 然后通过volumes的方式 加载到容器的/etc/ssl/certs/下 解决x509问题
# - ./ca/certs/ca-bundle.crt:/etc/ssl/certs/ca-bundler.crt
ports:
- 13006:13005
command: /bin/bash -c apt-get -qq update && \
apt-get -qq install -y --no-install-recommends ca-certificates curl && \ ./qg-blockchain-sdk-linux
networks:
compose_network:
ipv4_address: ${BCNET_PREFIX}.11
redis:
image: redis:latest
restart: always
command: redis-server --appendonly yes
volumes:
- './redis/data:/data'
ports:
- 16380:6379
networks:
compose_network:
ipv4_address: ${BCNET_PREFIX}.12
networks:
compose_network:
external: true
name: ${BCNET}
这几种方案 前几种太麻烦了 没试, 最后用第四种成功了。