赞
踩
最近需要对开源项目one-api进行k8s容器化部署,主要分以下几个步骤:
整个的篇幅比较长,将会分成上下两篇来阐述。
开源项目one-api已经提供了Dockerfile文件,按说制作一个私有镜像是非常简单的事情,可是却遇到了一个大坑。
主要是因为golang的版本问题。
官方Dockerfile所使用的是golang,并没有指定版本,也即golang:latest。
go version查看得到其版本为1.17。
这是我们要修改的第一点,指定golang的版本。
# 修改前
FROM golang AS builder2
# 修改后
FROM golang:1.19-alpine AS builder2
第二、我们在构建go项目的时候,增加国内镜像代理,以加速构建。
ENV GOPROXY=https://goproxy.cn,direct
第三、整个Dockerfile先是构建前端页面,再是构建go项目。本文主要是针对go项目的构建进行了改动。
完整的Dockerfile,修改后的内容,详见下:
# 指定golang的版本 FROM golang:1.19-alpine AS builder2 # 增加go镜像代理 ENV GOPROXY=https://goproxy.cn,direct \ GO111MODULE=on \ CGO_ENABLED=1 \ GOOS=linux # 切换工作目录至/build WORKDIR /build ADD go.mod go.sum ./ RUN go mod download # 安装C编译器 RUN apk add --no-cache build-base COPY . . COPY --from=builder /web/build ./web/build RUN go build -ldflags "-s -w -X 'github.com/songquanpeng/one-api/common.Version=$(cat VERSION)' -extldflags '-static'" -o one-api # 总结这一阶段,会在工作目录/build下生成一个可执行文件one-api # 下面是把它单拎出去,使用轻量级容器alpine,运行该可执行文件。 FROM alpine RUN apk update \ && apk upgrade \ && apk add --no-cache ca-certificates tzdata \ && update-ca-certificates 2>/dev/null || true # 把可执行文件/build/one-api拷贝至alpine系统的根目录/下 COPY --from=builder2 /build/one-api / EXPOSE 5175 # 切换工作目录至/data WORKDIR /data # 运行根目录下的可执行文件one-api ENTRYPOINT ["/one-api"]
/go/pkg/mod/github.com/jackc/pgx/v5@v5.5.4/pgtype/builtin_wrappers.go:9:2: package net/netip is not in GOROOT (/usr/local/go/src/net/netip)
在Go 1.17及以后的版本中,net/netip包已经被移动到golang.org/x/net模块中。这个错误的解决办法就是升级go版本。
github.com/mattn/go-sqlite3 cgo: C compiler “gcc” not found: exec: “gcc”: executable file not found in $PATH
安装CGO所需的C编译器和库,在RUN go mod download后面,在RUN go build的前面,增加命令:RUN apk add --no-cache build-base。(因为golang:1.19-alpine使用musl libc,而不是glibc,并且默认不包含gcc)
Step 20/29 : RUN go mod download
—> Running in f29cd7f8f144
go mod download: zip: not a valid zip file
这是因为网络慢导致的错误,解决版本是使用go镜像代理。
github.com/jackc/puddle/v2
/go/pkg/mod/github.com/jackc/puddle/v2@v2.2.1/pool.go:142:30: undefined: atomic.Int64
note: module requires Go 1.19
github.com/mattn/go-sqlite3
cgo: C compiler “gcc” not found: exec: “gcc”: executable file not found in $PATH
这个错误是当时使用了golang:1.19镜像,后修改为golang:1.19-alpine解决。
如果你根据报错信息去修改的话,可能会需要打印一些环境信息。
在构建docker镜像的过程中,还遇到许多报错,这里就不一一列举,报错的原因也都是因为golang的版本,期间使用过1.16/1.18/1.19,最后是使用1.19-alpine解决。
而one-api项目的go.mod文件指定使用1.18。
所以说,关于golang的版本问题很乱,我也是一通乱试。
在开发环境,我们只需新建数据库one_api即可。
但是,在生产环境,我们建议你手动建库建表.
CREATE DATABASE `one_api` /*!40100 DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_bin */; CREATE TABLE `one_api`.`abilities` ( `group` varchar(32) COLLATE utf8mb4_bin NOT NULL, `model` varchar(191) COLLATE utf8mb4_bin NOT NULL, `channel_id` bigint(20) NOT NULL, `enabled` tinyint(1) DEFAULT NULL, `priority` bigint(20) DEFAULT '0', PRIMARY KEY (`group`,`model`,`channel_id`), KEY `idx_abilities_priority` (`priority`), KEY `idx_abilities_channel_id` (`channel_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin; CREATE TABLE `one_api`.`channels` ( `id` bigint(20) NOT NULL AUTO_INCREMENT, `type` bigint(20) DEFAULT '0', `key` text COLLATE utf8mb4_bin, `status` bigint(20) DEFAULT '1', `name` varchar(191) COLLATE utf8mb4_bin DEFAULT NULL, `weight` bigint(20) unsigned DEFAULT '0', `created_time` bigint(20) DEFAULT NULL, `test_time` bigint(20) DEFAULT NULL, `response_time` bigint(20) DEFAULT NULL, `base_url` varchar(191) COLLATE utf8mb4_bin DEFAULT '', `other` longtext COLLATE utf8mb4_bin, `balance` double DEFAULT NULL, `balance_updated_time` bigint(20) DEFAULT NULL, `models` longtext COLLATE utf8mb4_bin, `group` varchar(32) COLLATE utf8mb4_bin DEFAULT 'default', `used_quota` bigint(20) DEFAULT '0', `model_mapping` varchar(1024) COLLATE utf8mb4_bin DEFAULT '', `priority` bigint(20) DEFAULT '0', `config` longtext COLLATE utf8mb4_bin, PRIMARY KEY (`id`), KEY `idx_channels_name` (`name`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin; CREATE TABLE `one_api`.`logs` ( `id` bigint(20) NOT NULL AUTO_INCREMENT, `user_id` bigint(20) DEFAULT NULL, `created_at` bigint(20) DEFAULT NULL, `type` bigint(20) DEFAULT NULL, `content` longtext COLLATE utf8mb4_bin, `username` varchar(191) COLLATE utf8mb4_bin DEFAULT '', `token_name` varchar(191) COLLATE utf8mb4_bin DEFAULT '', `model_name` varchar(191) COLLATE utf8mb4_bin DEFAULT '', `quota` bigint(20) DEFAULT '0', `prompt_tokens` bigint(20) DEFAULT '0', `completion_tokens` bigint(20) DEFAULT '0', `channel_id` bigint(20) DEFAULT NULL, PRIMARY KEY (`id`), KEY `index_username_model_name` (`model_name`,`username`), KEY `idx_logs_token_name` (`token_name`), KEY `idx_logs_model_name` (`model_name`), KEY `idx_logs_channel_id` (`channel_id`), KEY `idx_logs_user_id` (`user_id`), KEY `idx_created_at_type` (`created_at`,`type`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin; CREATE TABLE `one_api`.`options` ( `key` varchar(191) COLLATE utf8mb4_bin NOT NULL, `value` longtext COLLATE utf8mb4_bin, PRIMARY KEY (`key`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin; CREATE TABLE `one_api`.`redemptions` ( `id` bigint(20) NOT NULL AUTO_INCREMENT, `user_id` bigint(20) DEFAULT NULL, `key` char(32) COLLATE utf8mb4_bin DEFAULT NULL, `status` bigint(20) DEFAULT '1', `name` varchar(191) COLLATE utf8mb4_bin DEFAULT NULL, `quota` bigint(20) DEFAULT '100', `created_time` bigint(20) DEFAULT NULL, `redeemed_time` bigint(20) DEFAULT NULL, PRIMARY KEY (`id`), UNIQUE KEY `idx_redemptions_key` (`key`), KEY `idx_redemptions_name` (`name`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin; CREATE TABLE `one_api`.`tokens` ( `id` bigint(20) NOT NULL AUTO_INCREMENT, `user_id` bigint(20) DEFAULT NULL, `key` char(48) COLLATE utf8mb4_bin DEFAULT NULL, `status` bigint(20) DEFAULT '1', `name` varchar(191) COLLATE utf8mb4_bin DEFAULT NULL, `created_time` bigint(20) DEFAULT NULL, `accessed_time` bigint(20) DEFAULT NULL, `expired_time` bigint(20) DEFAULT '-1', `remain_quota` bigint(20) DEFAULT '0', `unlimited_quota` tinyint(1) DEFAULT '0', `used_quota` bigint(20) DEFAULT '0', `models` varchar(191) COLLATE utf8mb4_bin DEFAULT '', `subnet` varchar(191) COLLATE utf8mb4_bin DEFAULT '', PRIMARY KEY (`id`), UNIQUE KEY `idx_tokens_key` (`key`), KEY `idx_tokens_name` (`name`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin; CREATE TABLE `one_api`.`users` ( `id` bigint(20) NOT NULL AUTO_INCREMENT, `username` varchar(191) COLLATE utf8mb4_bin DEFAULT NULL, `password` longtext COLLATE utf8mb4_bin NOT NULL, `display_name` varchar(191) COLLATE utf8mb4_bin DEFAULT NULL, `role` bigint(20) DEFAULT '1', `status` bigint(20) DEFAULT '1', `email` varchar(191) COLLATE utf8mb4_bin DEFAULT NULL, `github_id` varchar(191) COLLATE utf8mb4_bin DEFAULT NULL, `wechat_id` varchar(191) COLLATE utf8mb4_bin DEFAULT NULL, `lark_id` varchar(191) COLLATE utf8mb4_bin DEFAULT NULL, `access_token` char(32) COLLATE utf8mb4_bin DEFAULT NULL, `quota` bigint(20) DEFAULT '0', `used_quota` bigint(20) DEFAULT '0', `request_count` bigint(20) DEFAULT '0', `group` varchar(32) COLLATE utf8mb4_bin DEFAULT 'default', `aff_code` varchar(32) COLLATE utf8mb4_bin DEFAULT NULL, `inviter_id` bigint(20) DEFAULT NULL, PRIMARY KEY (`id`), UNIQUE KEY `username` (`username`), UNIQUE KEY `idx_users_aff_code` (`aff_code`), UNIQUE KEY `idx_users_access_token` (`access_token`), KEY `idx_users_lark_id` (`lark_id`), KEY `idx_users_email` (`email`), KEY `idx_users_git_hub_id` (`github_id`), KEY `idx_users_we_chat_id` (`wechat_id`), KEY `idx_users_inviter_id` (`inviter_id`), KEY `idx_users_username` (`username`), KEY `idx_users_display_name` (`display_name`) ) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;
最后,登录用户初始化一个root用户:
INSERT INTO `one_api`.`users`
(id, username, password, display_name, `role`, status, email, github_id, wechat_id, lark_id, access_token, quota, used_quota, request_count, `group`, aff_code, inviter_id)
VALUES(1, 'root', '$2a$10$HAJRqAF884IGFJYvaAR.eu82GA8vNhQR.iQ0.jEYfovZNioyD91Te', 'Root User', 100, 1, '', '', '', '', '47d954235a724c399bfc3ea400eb3b2c', 500000000000000, 0, 0, 'default', '', 0);
非关系型数据库,不涉及ddl和dml了,仅给出连接地址的示例(区分有无密码)
无密码
redis://:192.168.80.116:6379
有密码
redis://:{password}:192.168.80.116:6379
测试并验证上面制作好的docker镜像,下文将把它部署到k8s容器里。
version: '3.4'
services:
one-api:
image: "xxx/one-api:1.0.0"
container_name: one-api
restart: always
command: --port 5175
ports:
- "5175:5175"
environment:
- SQL_DSN=root:123456@tcp(192.168.80.116:3306)/one_api # 修改此行,或注释掉以使用 SQLite 作为数据库
- REDIS_CONN_STRING=redis://:192.168.80.116:6379
- SESSION_SECRET=random_string # 修改为随机字符串
- TZ=Asia/Shanghai
[root@emc7 one-api]# docker-compose ps
Name Command State Ports
-------------------------------------------------------------------------
one-api /one-api --port 5175 Up 0.0.0.0:5175->5175/tcp
验证docker镜像后,推送至远程仓库,为下文k8s部署做准备。
[root@emc7 one-api]# docker images | grep one
xxx/one-api 1.0.0 c290c605bd1b 6 hours ago 72.1MB
xxx-harbor-registry.cn-hangzhou.cr.aliyuncs.com/xxx/one-api-web 1.0.0 c290c605bd1b 6 hours ago 72.1MB
[root@emc7 one-api]# docker tag c290c605bd1b xxx-harbor-registry.cn-hangzhou.cr.aliyuncs.com/xxx/one-api-web:1.0.0
[root@emc7 one-api]# docker login --username={用户名} xxx-harbor-registry.cn-hangzhou.cr.aliyuncs.com --password {密码}
[root@emc7 one-api]# docker push xxx-harbor-registry.cn-hangzhou.cr.aliyuncs.com/xxx/one-api-web:1.0.0
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。