docker-compose secrets MYSQL_ROOT_PASSWORD_FILE work correctly but DB_PASSWORD result empty string

huangapple go评论72阅读模式
英文:

docker-compose secrets MYSQL_ROOT_PASSWORD_FILE work correctly but DB_PASSWORD result empty string

问题

MYSQL_ROOT_PASSWORD_FILE在数据库容器中正常工作,但DB_PASSWORD为空字符串

在我的项目中,我使用React作为前端,使用Fiber框架的Golang作为后端,MySQL作为数据库。

当我在Dockerfile中设置环境变量时,它可以正常工作。但是当我使用docker-compose secrets时,在数据库容器中可以正常工作,但在后端容器中,环境变量的值为空字符串。

dockercompose.yml

version: '2.17.3'
services:
  backend:
    container_name: app-backend
    image: app-backend:private
    build: 
      context: ./server/.
      dockerfile: Dockerfile.private
    secrets:
      - db_password
      - db_name
      - jwt_secret_key
      - mailer_password
      - mailer_username
    environment:
      - DB_HOST=my-database
      - DB_PORT=3306
      - DB_USER=root
      - DB_PASSWORD_FILE=/run/secrets/db_password
      - DB_NAME_FILE=/run/secrets/db_name

      # Leave SERVER_HOST BLANK. Info: https://stackoverflow.com/a/61047889
      - SERVER_HOST=
      - SERVER_PORT=8080
      - WEBSITE_HOST=localhost:3000

      - JWT_SECRET_KEY_FILE=/run/secrets/jwt_secret_key

      - MAILER_HOST=smtp.gmail.com
      - MAILER_PORT=587
      - MAILER_USERNAME_FILE=/run/secrets/mailer_username
      - MAILER_PASSWORD_FILE=/run/secrets/mailer_password

      - ALLOW_ORIGINS=http://localhost:3000
    
    ports:
      - 8000:8080
    user: nonroot:nonroot
    networks:
      - my-network

  database:
    container_name: app-database
    image: mysql
    build:
      dockerfile: ./server/Dockerfile.database
    secrets:
      - db_root_password
    environment:
      - MYSQL_ROOT_PASSWORD_FILE=/run/secrets/db_root_password
    ports:
      - 3307:3306
    command: --default-authentication-plugin=mysql_native_password
    restart: unless-stopped
    networks:
      - my-network
   
networks:
  my-network:

secrets:
  db_root_password:
    file: ./secrets/db_root_password.txt
  db_password:
    file: ./secrets/db_password.txt
  db_name:
    file: ./secrets/db_name.txt
  jwt_secret_key: 
    file: ./secrets/jwt_secret_key.txt
  mailer_password:
    file: ./secrets/mailer_password.txt
  mailer_username:
    file: ./secrets/mailer_username.txt

Dockerfile.private

# syntax=docker/dockerfile:1

##
## Build the application from source
##

FROM golang:1.20.4-bullseye AS build-stage

WORKDIR /app

COPY go.mod go.sum ./
RUN go mod download && go mod verify

COPY . ./

RUN CGO_ENABLED=0 GOOS=linux go build -o main main.go

##
## Deploy the application binary into a lean image
##

FROM gcr.io/distroless/base-debian11 AS build-release-stage

WORKDIR /app

COPY --from=build-stage /app/main .

EXPOSE 8080

USER nonroot:nonroot

ENTRYPOINT ["/app/main"]

Dockerfile.database

# database
FROM mysql

EXPOSE 3306

CMD ["--default-authentication-plugin=mysql_native_password"]

构建脚本

docker-compose up -d --build

我已经检查了mysql数据库中的MYSQL_ROOT_PASSWORD_FILE=/run/secrets/db_root_password,它可以正常工作。我可以连接到数据库,但在后端中,Docker桌面日志显示为空字符串。

 ┌───────────────────────────────────────────────────┐ 
 │                   Fiber v2.45.0                   │ 
 │               http://127.0.0.1:8080               │ 
 │       (bound on host 0.0.0.0 and port 8080)       │ 
 │                                                   │ 
 │ Handlers ............ 49  Processes ........... 1 │ 
 │ Prefork ....... Disabled  PID ................. 1 │ 
 └───────────────────────────────────────────────────┘ 
2023/05/22 22:21:30 Try connecting to database: %w root:@tcp(nf-theater-database:3306)/?parseTime=true

这是我的Golang连接代码:

package database

import (
	"database/sql"
	"fmt"
	"log"
	"os"
)

func Connect() *sql.DB {
	dbUser := os.Getenv("DB_USER")
	dbPassword := os.Getenv("DB_PASSWORD")
	dbHost := os.Getenv("DB_HOST")
	dbPort := os.Getenv("DB_PORT")
	dbName := os.Getenv("DB_NAME")

	connString := fmt.Sprintf("%s:%s@tcp(%s:%s)/%s?parseTime=true", dbUser, dbPassword, dbHost, dbPort, dbName)
	log.Println("Try connecting to database: %w", connString)
	// Open database connection
	db, err := sql.Open("mysql", connString)
	if err != nil {
		fmt.Println(err.Error())
	}

	return db
}

我尝试将docker-compose的第一行版本从version: '2.17.3'更改为version: '3.8',但结果仍然相同。

我不明白为什么它不起作用。如果不必要,我不想切换到Swarm。我该如何解决这个问题?

英文:

MYSQL_ROOT_PASSWORD_FILE work correctly but DB_PASSWORD result empty string

In my project. I use react as frontend, golang with fiber framework as backend and mysql as database.

It work fine when I set ENV in Dockerfile. but when I work with docker-compose secrets. In database container work correctly but in backend container. The environment variable result empty string,

dockercompose.yml

version: '2.17.3'
backend:
container_name: app-backend
image: app-backend:private
build: 
context: ./server/.
dockerfile: Dockerfile.private
secrets:
- db_password
- db_name
- jwt_secret_key
- mailer_password
- mailer_username
environment:
- DB_HOST=my-database
- DB_PORT=3306
- DB_USER=root
- DB_PASSWORD_FILE=/run/secrets/db_password
- DB_NAME_FILE=/run/secrets/db_name
# Leave SERVER_HOST BLANK. Info: https://stackoverflow.com/a/61047889
- SERVER_HOST=
- SERVER_PORT=8080
- WEBSITE_HOST=localhost:3000
- JWT_SECRET_KEY_FILE=/run/secrets/jwt_secret_key
- MAILER_HOST=smtp.gmail.com
- MAILER_PORT=587
- MAILER_USERNAME_FILE=/run/secrets/mailer_username
- MAILER_PASSWORD_FILE=/run/secrets/mailer_password
- ALLOW_ORIGINS=http://localhost:3000
ports:
- 8000:8080
user: nonroot:nonroot
networks:
- my-network
database:
container_name: app-database
image: mysql
build:
dockerfile: ./server/Dockerfile.database
secrets:
- db_root_password
environment:
- MYSQL_ROOT_PASSWORD_FILE=/run/secrets/db_root_password
ports:
- 3307:3306
command: --default-authentication-plugin=mysql_native_password
restart: unless-stopped
networks:
- my-network
networks:
my-network:
secrets:
db_root_password:
file: ./secrets/db_root_password.txt
db_password:
file: ./secrets/db_password.txt
db_name:
file: ./secrets/db_name.txt
jwt_secret_key: 
file: ./secrets/jwt_secret_key.txt
mailer_password:
file: ./secrets/mailer_password.txt
mailer_username:
file: ./secrets/mailer_username.txt

Dockerfile.private

# syntax=docker/dockerfile:1
##
## Build the application from source
##
FROM golang:1.20.4-bullseye AS build-stage
WORKDIR /app
COPY go.mod go.sum ./
RUN go mod download && go mod verify
COPY . ./
RUN CGO_ENABLED=0 GOOS=linux go build -o main main.go
##
## Deploy the application binary into a lean image
##
FROM gcr.io/distroless/base-debian11 AS build-release-stage
WORKDIR /app
COPY --from=build-stage /app/main .
EXPOSE 8080
USER nonroot:nonroot
ENTRYPOINT ["/app/main"]

Dockerfile.database

# database
FROM mysql
EXPOSE 3306
CMD ["--default-authentication-plugin=mysql_native_password"]

build script

docker-compose up -d --build

I've check MYSQL_ROOT_PASSWORD_FILE=/run/secrets/db_root_password in mysql database. It work correctly. I can connect to database. but in backend. In docker-desktop logs show it have empty string

 ┌───────────────────────────────────────────────────┐ 
│                   Fiber v2.45.0                   │ 
│               http://127.0.0.1:8080               │ 
│       (bound on host 0.0.0.0 and port 8080)       │ 
│                                                   │ 
│ Handlers ............ 49  Processes ........... 1 │ 
│ Prefork ....... Disabled  PID ................. 1 │ 
└───────────────────────────────────────────────────┘ 
2023/05/22 22:21:30 Try connecting to database: %w root:@tcp(nf-theater-database:3306)/?parseTime=true

Here my golang connection code

package database
import (
"database/sql"
"fmt"
"log"
"os"
)
func Connect() *sql.DB {
dbUser := os.Getenv("DB_USER")
dbPassword := os.Getenv("DB_PASSWORD")
dbHost := os.Getenv("DB_HOST")
dbPort := os.Getenv("DB_PORT")
dbName := os.Getenv("DB_NAME")
connString := fmt.Sprintf("%s:%s@tcp(%s:%s)/%s?parseTime=true", dbUser, dbPassword, dbHost, dbPort, dbName)
log.Println("Try connecting to database: %w", connString)
// Open database connection
db, err := sql.Open("mysql", connString)
if err != nil {
fmt.Println(err.Error())
}
return db
}

I've try to change version in first line of docker-compose from version: '2.17.3' to version: '3.8' but result was the same

I don't understand why it's don't work. I don't want to switch to swarm if it don't have to. How can I fix this?

答案1

得分: 0

MYSQL docker-entrypoint.sh 检查环境变量 MYSQL_ROOT_PASSWORD_FILE,如果存在,则将变量中指定的文件内容加载到环境变量 MYSQL_ROOT_PASSWORD 中(然后在脚本的其他地方将其用作密码)。

因此,没有特殊处理以 _FILE 结尾的变量;容器中的某个组件需要检查该变量并从文件中加载数据。

你的 docker-compose.yml 设置了变量 DB_PASSWORD_FILE 并直接运行应用程序(ENTRYPOINT ["/app/main"])。然后你尝试读取 DB_PASSWORDdbPassword := os.Getenv("DB_PASSWORD"));这将为空,因为你没有设置该环境变量。

你可以添加一个类似于 MYSQL 容器中使用的脚本,或者直接读取设置的变量,例如:

dbPasswordFile := os.Getenv("DB_PASSWORD_FILE")
dbPassword, err := os.ReadFile(dbPasswordFile)

注意:你应该检查空变量并处理任何错误

英文:

The MYSQL docker-entrypoint.sh checks for the environment variable MYSQL_ROOT_PASSWORD_FILE and, if present, loads the contents of the file named in the variable into the environmental variable MYSQL_ROOT_PASSWORD (which is then used elsewhere in the script as the password).

So there is no special handling of variables ending with _FILE; something in the container needs to check for the variable and load the data from the file.

Your docker-compose.yml sets the variable DB_PASSWORD_FILE and runs your application directly (ENTRYPOINT ["/app/main"]). You then attempt to read DB_PASSWORD (dbPassword := os.Getenv("DB_PASSWORD")); this will be empty because you have not set that environmental variable.

You could add a script, similar to that used in the MYSQL container, or just read the variable as set e.g.

dbPasswordFile := os.Getenv("DB_PASSWORD_FILE")
dbPassword, err := os.ReadFile(dbPasswordFile)

Note: You should probably check for a blank variable and handle any errors

huangapple
  • 本文由 发表于 2023年5月23日 07:06:33
  • 转载请务必保留本文链接:https://go.coder-hub.com/76310374.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定