🐳 optimized docker packaging
This commit is contained in:
4
.idea/GOHCache.xml
generated
4
.idea/GOHCache.xml
generated
@@ -1489,7 +1489,7 @@
|
||||
<entry key="file://$PROJECT_DIR$/app/aisvc/rpc/internal/logic/aiservice/face_recognition_logic.go">
|
||||
<value>
|
||||
<ScannedPath>
|
||||
<option name="lastModified" value="1737604866085" />
|
||||
<option name="lastModified" value="1737629887959" />
|
||||
<option name="schema">
|
||||
<list>
|
||||
<option value="FaceRecognitionLogic" />
|
||||
@@ -2117,7 +2117,7 @@
|
||||
<entry key="file://$PROJECT_DIR$/app/auth/api/internal/logic/storage/upload_file_logic.go">
|
||||
<value>
|
||||
<ScannedPath>
|
||||
<option name="lastModified" value="1737533110977" />
|
||||
<option name="lastModified" value="1737629820919" />
|
||||
<option name="schema">
|
||||
<list>
|
||||
<option value="UploadFileLogic" />
|
||||
|
@@ -9,18 +9,14 @@ LABEL maintainer="landaiqing <<landaiqing@126.com>>"
|
||||
ENV TZ=Asia/Shanghai \
|
||||
DEBIAN_FRONTEND=noninteractive
|
||||
|
||||
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
|
||||
|
||||
RUN sed -i 's|http://deb.debian.org/debian|https://mirrors.tuna.tsinghua.edu.cn/debian|g' /etc/apt/sources.list && \
|
||||
apt-get update && apt-get install -y --no-install-recommends --fix-missing \
|
||||
tzdata git build-essential cmake pkg-config wget unzip libgtk2.0-dev \
|
||||
curl ca-certificates libcurl4-openssl-dev libssl-dev \
|
||||
libavcodec-dev libavformat-dev libswscale-dev libtbb2 libtbb-dev \
|
||||
libharfbuzz-dev libfreetype6-dev \
|
||||
libjpeg-dev libturbojpeg-dev libpng-dev libtiff-dev libdc1394-22-dev nasm \
|
||||
libdlib-dev libblas-dev libatlas-base-dev liblapack-dev \
|
||||
gcc g++ musl-dev cmake && \
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone && \
|
||||
sed -i 's|http://deb.debian.org/debian|https://mirrors.tuna.tsinghua.edu.cn/debian|g' /etc/apt/sources.list && \
|
||||
apt-get update && apt-get install -y --no-install-recommends \
|
||||
tzdata git build-essential cmake pkg-config unzip curl ca-certificates \
|
||||
libcurl4-openssl-dev libssl-dev libturbojpeg-dev \
|
||||
libpng-dev libtiff-dev nasm libblas-dev libatlas-base-dev\
|
||||
libdlib-dev libjpeg62-turbo-dev liblapack-dev && \
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
|
||||
ARG OPENCV_VERSION="4.11.0"
|
||||
|
||||
@@ -71,8 +67,6 @@ WORKDIR /app
|
||||
|
||||
COPY . .
|
||||
|
||||
#WORKDIR /app/app/aisvc/
|
||||
|
||||
ENV CGO_ENABLED=1 \
|
||||
CGO_CFLAGS="-I/usr/local/include/opencv4" \
|
||||
CGO_CPPFLAGS="-I/usr/local/include" \
|
||||
@@ -81,13 +75,8 @@ ENV CGO_ENABLED=1 \
|
||||
GOARCH=amd64 \
|
||||
GOPROXY=https://goproxy.cn,direct
|
||||
|
||||
RUN go mod download
|
||||
|
||||
RUN go build -ldflags="-w -s" -o schisandra-ai-server ./app/aisvc/rpc/aisvc.go
|
||||
|
||||
#EXPOSE 8888
|
||||
#
|
||||
#CMD ["./schisandra-ai-server"]
|
||||
RUN go mod download && \
|
||||
go build -ldflags="-w -s" -o schisandra-ai-server ./app/aisvc/rpc/aisvc.go
|
||||
|
||||
FROM debian:bullseye-slim AS runtime
|
||||
|
||||
@@ -96,17 +85,13 @@ ENV TZ=Asia/Shanghai \
|
||||
|
||||
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone && \
|
||||
apt-get update && apt-get install -y --no-install-recommends \
|
||||
tzdata libjpeg62-turbo libpng16-16 libtiff5 libturbojpeg0 \
|
||||
libharfbuzz0b libfreetype6 libavcodec58 libavformat58 libswscale5 libtbb2 \
|
||||
libblas3 liblapack3 && \
|
||||
tzdata libjpeg62-turbo libblas3 liblapack3 libdlib-dev libtiff5 && \
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
COPY --from=builder /usr/local/lib /usr/local/lib/
|
||||
|
||||
COPY --from=builder /usr/lib/ /usr/lib/
|
||||
|
||||
COPY --from=builder /usr/local/include/opencv4 /usr/local/include/opencv4/
|
||||
|
||||
COPY --from=builder /app/schisandra-ai-server .
|
||||
@@ -117,9 +102,6 @@ COPY --from=builder /app/app/aisvc/resources ./resources
|
||||
|
||||
ENV LD_LIBRARY_PATH=/usr/local/lib
|
||||
|
||||
RUN echo "/usr/local/lib" > /etc/ld.so.conf.d/custom-libs.conf && ldconfig
|
||||
|
||||
|
||||
EXPOSE 8888
|
||||
|
||||
CMD ["./schisandra-ai-server"]
|
||||
|
@@ -10,6 +10,7 @@ import (
|
||||
"github.com/zeromicro/go-zero/core/logx"
|
||||
"image"
|
||||
"image/jpeg"
|
||||
_ "image/png"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"schisandra-album-cloud-microservices/app/aisvc/model/mysql/model"
|
||||
@@ -47,6 +48,9 @@ func (l *FaceRecognitionLogic) FaceRecognition(in *pb.FaceRecognitionRequest) (*
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if toJPEG == nil {
|
||||
return nil, nil
|
||||
}
|
||||
// 提取人脸特征
|
||||
faceFeatures, err := l.svcCtx.FaceRecognizer.RecognizeSingle(toJPEG)
|
||||
if err != nil {
|
||||
@@ -96,18 +100,21 @@ func (l *FaceRecognitionLogic) FaceRecognition(in *pb.FaceRecognitionRequest) (*
|
||||
return l.saveNewFace(in, faceFeatures, hashKey)
|
||||
}
|
||||
|
||||
// ConvertImageToJPEG 将非 JPEG 格式的图片字节数据转换为 JPEG
|
||||
func (l *FaceRecognitionLogic) ConvertImageToJPEG(imageData []byte) ([]byte, error) {
|
||||
// 使用 image.Decode 解码图像数据
|
||||
img, _, err := image.Decode(bytes.NewReader(imageData))
|
||||
|
||||
// 解码图片
|
||||
img, format, err := image.Decode(bytes.NewReader(imageData))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to decode image: %v", err)
|
||||
}
|
||||
|
||||
// 创建一个缓冲区来存储 JPEG 格式的数据
|
||||
var jpegBuffer bytes.Buffer
|
||||
// 如果已经是 JPEG 格式,则直接返回原数据
|
||||
if format == "jpeg" {
|
||||
return imageData, nil
|
||||
}
|
||||
|
||||
// 将图片编码为 JPEG 格式
|
||||
// 如果是 PNG 格式,则转换为 JPEG
|
||||
var jpegBuffer bytes.Buffer
|
||||
err = jpeg.Encode(&jpegBuffer, img, nil)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to encode image to JPEG: %v", err)
|
||||
|
@@ -56,26 +56,29 @@ func (l *UploadFileLogic) UploadFile(r *http.Request) (resp string, err error) {
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
var faceId int64
|
||||
var faceId int64 = 0
|
||||
var className string
|
||||
bytes, err := io.ReadAll(file)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
// 人脸识别
|
||||
face, err := l.svcCtx.AiSvcRpc.FaceRecognition(l.ctx, &pb.FaceRecognitionRequest{Face: bytes, UserId: uid})
|
||||
if err != nil {
|
||||
return "", err
|
||||
if result.FileType == "image/png" || result.FileType == "image/jpeg" {
|
||||
face, err := l.svcCtx.AiSvcRpc.FaceRecognition(l.ctx, &pb.FaceRecognitionRequest{Face: bytes, UserId: uid})
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if face != nil {
|
||||
faceId = face.GetFaceId()
|
||||
}
|
||||
|
||||
// 图像分类
|
||||
classification, err := l.svcCtx.AiSvcRpc.TfClassification(l.ctx, &pb.TfClassificationRequest{Image: bytes})
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
className = classification.GetClassName()
|
||||
}
|
||||
if face != nil {
|
||||
faceId = face.GetFaceId()
|
||||
}
|
||||
// 分类
|
||||
classification, err := l.svcCtx.AiSvcRpc.TfClassification(l.ctx, &pb.TfClassificationRequest{Image: bytes})
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
fmt.Println(classification.ClassName)
|
||||
fmt.Println(classification.Score)
|
||||
|
||||
// 解析 EXIF 信息
|
||||
exif, err := l.parseExifData(result.Exif)
|
||||
@@ -99,12 +102,13 @@ func (l *UploadFileLogic) UploadFile(r *http.Request) (resp string, err error) {
|
||||
}
|
||||
|
||||
// 上传文件到 OSS
|
||||
if err = l.uploadFileToOSS(uid, header, file); err != nil {
|
||||
bucket, provider, err := l.uploadFileToOSS(uid, header, file)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
// 将 EXIF 和文件信息存入数据库
|
||||
if err = l.saveFileInfoToDB(uid, header, result, originalDateTime, gpsString, locationString, exif, faceId); err != nil {
|
||||
if err = l.saveFileInfoToDB(uid, bucket, provider, header, result, originalDateTime, gpsString, locationString, exif, faceId, className); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
@@ -220,20 +224,20 @@ func (l *UploadFileLogic) getGeoLocation(latitude, longitude float64) (string, s
|
||||
}
|
||||
|
||||
// 上传文件到 OSS
|
||||
func (l *UploadFileLogic) uploadFileToOSS(uid string, header *multipart.FileHeader, file multipart.File) error {
|
||||
func (l *UploadFileLogic) uploadFileToOSS(uid string, header *multipart.FileHeader, file multipart.File) (string, string, error) {
|
||||
ossConfig := l.svcCtx.DB.ScaStorageConfig
|
||||
dbConfig, err := ossConfig.Where(ossConfig.UserID.Eq(uid)).First()
|
||||
if err != nil {
|
||||
return errors.New("oss config not found")
|
||||
return "", "", errors.New("oss config not found")
|
||||
}
|
||||
|
||||
accessKey, err := encrypt.Decrypt(dbConfig.AccessKey, l.svcCtx.Config.Encrypt.Key)
|
||||
if err != nil {
|
||||
return errors.New("decrypt access key failed")
|
||||
return "", "", errors.New("decrypt access key failed")
|
||||
}
|
||||
secretKey, err := encrypt.Decrypt(dbConfig.SecretKey, l.svcCtx.Config.Encrypt.Key)
|
||||
if err != nil {
|
||||
return errors.New("decrypt secret key failed")
|
||||
return "", "", errors.New("decrypt secret key failed")
|
||||
}
|
||||
|
||||
storageConfig := &config.StorageConfig{
|
||||
@@ -247,31 +251,34 @@ func (l *UploadFileLogic) uploadFileToOSS(uid string, header *multipart.FileHead
|
||||
|
||||
service, err := l.svcCtx.StorageManager.GetStorage(uid, storageConfig)
|
||||
if err != nil {
|
||||
return errors.New("get storage failed")
|
||||
return "", "", errors.New("get storage failed")
|
||||
}
|
||||
|
||||
_, err = service.UploadFileSimple(l.ctx, dbConfig.Bucket, header.Filename, file, map[string]string{})
|
||||
if err != nil {
|
||||
return errors.New("upload file failed")
|
||||
return "", "", errors.New("upload file failed")
|
||||
}
|
||||
return nil
|
||||
return dbConfig.Bucket, dbConfig.Type, nil
|
||||
}
|
||||
|
||||
// 将 EXIF 和文件信息存入数据库
|
||||
func (l *UploadFileLogic) saveFileInfoToDB(uid string, header *multipart.FileHeader, result types.File, originalDateTime, gpsString, locationString string, exif map[string]interface{}, faceId int64) error {
|
||||
func (l *UploadFileLogic) saveFileInfoToDB(uid, bucket, provider string, header *multipart.FileHeader, result types.File, originalDateTime, gpsString, locationString string, exif map[string]interface{}, faceId int64, className string) error {
|
||||
exifJSON, err := json.Marshal(exif)
|
||||
if err != nil {
|
||||
return errors.New("marshal exif failed")
|
||||
}
|
||||
|
||||
var landscape string
|
||||
if result.Landscape != "none" {
|
||||
landscape = result.Landscape
|
||||
}
|
||||
scaStorageInfo := &model.ScaStorageInfo{
|
||||
UserID: uid,
|
||||
Provider: result.FileType,
|
||||
Bucket: result.TopCategory,
|
||||
Provider: provider,
|
||||
Bucket: bucket,
|
||||
FileName: header.Filename,
|
||||
FileSize: strconv.FormatInt(header.Size, 10),
|
||||
FileType: result.FileType,
|
||||
Landscape: result.Landscape,
|
||||
Landscape: landscape,
|
||||
Objects: strings.Join(result.ObjectArray, ", "),
|
||||
Anime: strconv.FormatBool(result.IsAnime),
|
||||
Category: result.TopCategory,
|
||||
@@ -281,6 +288,7 @@ func (l *UploadFileLogic) saveFileInfoToDB(uid string, header *multipart.FileHea
|
||||
Location: locationString,
|
||||
Exif: string(exifJSON),
|
||||
FaceID: faceId,
|
||||
Tags: className,
|
||||
}
|
||||
|
||||
err = l.svcCtx.DB.ScaStorageInfo.Create(scaStorageInfo)
|
||||
|
@@ -28,9 +28,8 @@ FROM alpine:latest
|
||||
ENV TZ=Asia/Shanghai \
|
||||
DEBIAN_FRONTEND=noninteractive
|
||||
|
||||
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
|
||||
|
||||
RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories && \
|
||||
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone && \
|
||||
sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories && \
|
||||
apk add --no-cache tzdata libjpeg-turbo
|
||||
|
||||
WORKDIR /app
|
||||
|
Reference in New Issue
Block a user