From 511155e0a7f004deee24baad9cd534a7304b69b1 Mon Sep 17 00:00:00 2001 From: "n.nakhostin" Date: Sun, 31 Aug 2025 14:16:37 +0330 Subject: [PATCH] Refactor Dockerfile and CI Configuration - Updated the CI configuration in .drone.yml to use the new Dockerfile located at ./cmd/web/Dockerfile. - Removed the old Dockerfile and Dockerfile-drone as they are no longer needed. - Refactored the cmd/web/Dockerfile to streamline the build process and improve organization. - Introduced a new bootstrap package to handle application initialization, including configuration, logging, MongoDB, Redis, and authorization service setup. - Added a health check endpoint for monitoring the server status, enhancing the API's operational capabilities. --- .drone.yml | 24 +++++------ Dockerfile | 60 ---------------------------- Dockerfile-drone | 17 -------- cmd/web/Dockerfile | 29 ++++++-------- cmd/web/{ => bootstrap}/bootstrap.go | 14 +++---- cmd/web/{ => bootstrap}/config.go | 2 +- cmd/web/{ => bootstrap}/health.go | 2 +- cmd/web/main.go | 15 +++---- 8 files changed, 42 insertions(+), 121 deletions(-) delete mode 100644 Dockerfile delete mode 100644 Dockerfile-drone rename cmd/web/{ => bootstrap}/bootstrap.go (93%) rename cmd/web/{ => bootstrap}/config.go (98%) rename cmd/web/{ => bootstrap}/health.go (98%) diff --git a/.drone.yml b/.drone.yml index 788fffb..63204f7 100644 --- a/.drone.yml +++ b/.drone.yml @@ -27,21 +27,21 @@ steps: username: cicd password: from_secret: REGISTRY_PASSWORD - dockerfile: Dockerfile-drone + dockerfile: ./cmd/web/Dockerfile repo: artifactory.ravanertebat.ir/tm/web registry: artifactory.ravanertebat.ir - - name: buid scraper - image: plugins/docker - settings: - build_args: - - BUILD_APP=scraper - username: cicd - password: - from_secret: REGISTRY_PASSWORD - dockerfile: Dockerfile-drone - repo: artifactory.ravanertebat.ir/tm/scraper - registry: artifactory.ravanertebat.ir + # - name: buid scraper + # image: plugins/docker + # settings: + # build_args: + # - BUILD_APP=scraper + # username: cicd + # password: + # from_secret: REGISTRY_PASSWORD + # dockerfile: Dockerfile-drone + # repo: artifactory.ravanertebat.ir/tm/scraper + # registry: artifactory.ravanertebat.ir node: tag: aecde-docker-runner diff --git a/Dockerfile b/Dockerfile deleted file mode 100644 index 8486345..0000000 --- a/Dockerfile +++ /dev/null @@ -1,60 +0,0 @@ -# Build stage -FROM golang:1.21-alpine AS builder - -# Install git and ca-certificates (needed for go mod download) -RUN apk add --no-cache git ca-certificates tzdata - -# Create non-root user for security -RUN addgroup -g 1001 -S appgroup && \ - adduser -u 1001 -S appuser -G appgroup - -# Set working directory -WORKDIR /app - -# Copy go mod files -COPY go.mod go.sum ./ - -# Download dependencies -RUN go mod download - -# Copy source code -COPY . . - -# Build the application -RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build \ - -ldflags='-w -s -extldflags "-static"' \ - -a -installsuffix cgo \ - -o bin/api \ - cmd/api/main.go - -# Final stage -FROM scratch - -# Copy ca-certificates from builder -COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ - -# Copy timezone data -COPY --from=builder /usr/share/zoneinfo /usr/share/zoneinfo - -# Copy user information from builder -COPY --from=builder /etc/passwd /etc/passwd -COPY --from=builder /etc/group /etc/group - -# Copy the binary -COPY --from=builder /app/bin/api /api - -# Copy configuration -COPY --from=builder /app/configs /configs - -# Use non-root user -USER appuser:appgroup - -# Expose port -EXPOSE 8081 - -# Health check -HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \ - CMD ["/api", "-health-check"] || exit 1 - -# Set entrypoint -ENTRYPOINT ["/api"] \ No newline at end of file diff --git a/Dockerfile-drone b/Dockerfile-drone deleted file mode 100644 index e3db804..0000000 --- a/Dockerfile-drone +++ /dev/null @@ -1,17 +0,0 @@ -ARG GO_VERSION=1.23 -ARG BASH_VERSION=5.0 -ARG BUILD_APP=web - -FROM golang:${GO_VERSION} AS goBuilder -WORKDIR /go/src/company/tm_back -COPY . . -RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -v -o ${BUILD_APP} ./cmd/${BUILD_APP}/main.go - -FROM bash:${BASH_VERSION} -RUN apk --no-cache add busybox-suid curl rsync tzdata tcpdump tree ca-certificates s-nail \ - && ln -s /usr/bin/mail /usr/bin/s-nail \ - && mkdir -p /go/bin/media /go/bin/log /go/bin/config -WORKDIR /go/bin -COPY --from=goBuilder /go/src/company/tm_back/${BUILD_APP} . -EXPOSE 8090 -ENTRYPOINT /go/bin/${BUILD_APP} diff --git a/cmd/web/Dockerfile b/cmd/web/Dockerfile index 93986df..70b4479 100644 --- a/cmd/web/Dockerfile +++ b/cmd/web/Dockerfile @@ -1,25 +1,22 @@ ARG GO_VERSION=1.23 ARG BASH_VERSION=5.0 -FROM golang:$GO_VERSION AS goBuilder -RUN mkdir -p /usr/local/go/src/company/tm_back -COPY . /go/src/company/tm_back/ -RUN echo $GOROOT +FROM golang:${GO_VERSION} AS go-builder -RUN cd /go/src/company/tm_back \ - && CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -v -o web ./cmd/web/main.go +WORKDIR /go/src/company/tm_back +COPY . . -FROM amd64/bash:$BASH_VERSION +RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -v -o web-build ./cmd/web/main.go -RUN apk --no-cache add --update busybox-suid \ - && apk --no-cache add curl rsync tzdata tcpdump tree ca-certificates s-nail \ +FROM bash:${BASH_VERSION} +RUN apk --no-cache add busybox-suid curl rsync tzdata tcpdump tree ca-certificates s-nail \ && ln -s /usr/bin/mail /usr/bin/s-nail \ - && mkdir -p /go/bin/media \ - && mkdir -p /go/bin/log \ - && mkdir -p /go/bin/config -WORKDIR /go/bin/ -COPY --from=goBuilder /go/src/company/tm_back/web . + && mkdir -p /go/bin/media /go/bin/log /go/bin/config +WORKDIR /go/bin + +COPY --from=go-builder /go/src/company/tm_back/web-build . + EXPOSE 8090 -# Set the binary. -ENTRYPOINT ["/go/bin/web"] \ No newline at end of file + +ENTRYPOINT /go/bin/web-build diff --git a/cmd/web/bootstrap.go b/cmd/web/bootstrap/bootstrap.go similarity index 93% rename from cmd/web/bootstrap.go rename to cmd/web/bootstrap/bootstrap.go index 7457359..9ce57c2 100644 --- a/cmd/web/bootstrap.go +++ b/cmd/web/bootstrap/bootstrap.go @@ -1,4 +1,4 @@ -package main +package bootstrap import ( "fmt" @@ -16,7 +16,7 @@ import ( ) // Init Application Configuration -func initConfig() Config { +func InitConfig() Config { conf, err := config.LoadConfig(".", &Config{}) if err != nil { panic(fmt.Sprintf("Failed to load config: %v", err)) @@ -26,7 +26,7 @@ func initConfig() Config { } // Init Logger Service -func initLogger(conf config.LoggingConfig) logger.Logger { +func InitLogger(conf config.LoggingConfig) logger.Logger { return logger.NewLogger(&logger.Config{ Level: conf.Level, Format: conf.Format, @@ -42,7 +42,7 @@ func initLogger(conf config.LoggingConfig) logger.Logger { } // Init MongoDB Connection Manager -func initMongoDB(conf config.MongoConfig, log logger.Logger) *mongo.ConnectionManager { +func InitMongoDB(conf config.MongoConfig, log logger.Logger) *mongo.ConnectionManager { // Convert infra.MongoConfig to mongo.ConnectionConfig connectionConfig := mongo.ConnectionConfig{ URI: conf.URI, @@ -75,7 +75,7 @@ func initMongoDB(conf config.MongoConfig, log logger.Logger) *mongo.ConnectionMa } // initHTTPServer initializes the Echo HTTP server with middleware -func initHTTPServer(conf Config, log logger.Logger) *echo.Echo { +func InitHTTPServer(conf Config, log logger.Logger) *echo.Echo { e := echo.New() // Configure Echo @@ -129,7 +129,7 @@ func initHTTPServer(conf Config, log logger.Logger) *echo.Echo { } // Init Redis Connection Manager -func initRedis(conf config.RedisConfig, log logger.Logger) redis.Client { +func InitRedis(conf config.RedisConfig, log logger.Logger) redis.Client { connectionConfig := &redis.Config{ Host: conf.Host, Port: conf.Port, @@ -158,7 +158,7 @@ func initRedis(conf config.RedisConfig, log logger.Logger) redis.Client { } // Init Authorization Service -func initAuthorizationService(conf JWTConfig, redisClient redis.Client, log logger.Logger) authorization.AuthorizationService { +func InitAuthorizationService(conf JWTConfig, redisClient redis.Client, log logger.Logger) authorization.AuthorizationService { authConfig := &authorization.AuthorizationConfig{ AccessTokenSecret: conf.AccessSecret, RefreshTokenSecret: conf.RefreshSecret, diff --git a/cmd/web/config.go b/cmd/web/bootstrap/config.go similarity index 98% rename from cmd/web/config.go rename to cmd/web/bootstrap/config.go index 6e9ac52..087b001 100644 --- a/cmd/web/config.go +++ b/cmd/web/bootstrap/config.go @@ -1,4 +1,4 @@ -package main +package bootstrap import ( "tm/pkg/config" diff --git a/cmd/web/health.go b/cmd/web/bootstrap/health.go similarity index 98% rename from cmd/web/health.go rename to cmd/web/bootstrap/health.go index a31dee7..eeb0651 100644 --- a/cmd/web/health.go +++ b/cmd/web/bootstrap/health.go @@ -1,4 +1,4 @@ -package main +package bootstrap import ( "net/http" diff --git a/cmd/web/main.go b/cmd/web/main.go index 34f0418..d3493d7 100644 --- a/cmd/web/main.go +++ b/cmd/web/main.go @@ -71,18 +71,19 @@ import ( "tm/internal/tender_approval" "tm/internal/user" + "tm/cmd/web/bootstrap" _ "tm/cmd/web/docs" // This is generated by swag "tm/cmd/web/router" ) func main() { - conf := initConfig() + conf := bootstrap.InitConfig() - logger := initLogger(conf.Logging) + logger := bootstrap.InitLogger(conf.Logging) defer logger.Sync() // Initialize MongoDB connection manager - mongoManager := initMongoDB(conf.Database.MongoDB, logger) + mongoManager := bootstrap.InitMongoDB(conf.Database.MongoDB, logger) defer func() { ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) defer cancel() @@ -94,7 +95,7 @@ func main() { }() // Initialize Redis connection manager - redisClient := initRedis(conf.Cache.Redis, logger) + redisClient := bootstrap.InitRedis(conf.Cache.Redis, logger) defer func() { if err := redisClient.Close(); err != nil { logger.Error("Failed to close Redis connection", map[string]interface{}{ @@ -104,8 +105,8 @@ func main() { }() // Initialize authorization service - userAuthService := initAuthorizationService(conf.UserAuth.JWT, redisClient, logger) - customerAuthService := initAuthorizationService(conf.CustomerAuth.JWT, redisClient, logger) + userAuthService := bootstrap.InitAuthorizationService(conf.UserAuth.JWT, redisClient, logger) + customerAuthService := bootstrap.InitAuthorizationService(conf.CustomerAuth.JWT, redisClient, logger) // Initialize repositories with MongoDB connection manager userRepository := user.NewUserRepository(mongoManager, logger) @@ -145,7 +146,7 @@ func main() { }) // Initialize HTTP server - e := initHTTPServer(conf, logger) + e := bootstrap.InitHTTPServer(conf, logger) // Register routes router.RegisterAdminRoutes(e, userHandler, companyHandler, customerHandler, tenderHandler, feedbackHandler, tenderApprovalHandler)