英文:
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_PASSWORD
(dbPassword := 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
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论