使用容器化的 Next.js + Flask + PostgreSQL 应用程序的问题
使用容器化的 Next.js + Flask + PostgreSQL 应用程序的问题
问题:
我一直在尝试将我的应用程序容器化,包括Next.js前端、Flask后端和PostgreSQL数据库,但是遇到了很多问题。目前的主要问题是我的PostgreSQL模式没有正确加载。
目录结构:
|-- docker-compose.yaml |-- backend | |-- Dockerfile | `-- app.py |-- database | |-- 01-schema.sql | |-- 02-init.sql | `-- Dockerfile `-- frontend |-- Dockerfile `-- (...Next.js应用程序文件)
docker-compose.yaml
:
services:
database:
image: postgres:latest
restart: always
environment:
- POSTGRES_USER=postgres
- POSTGRES_PASSWORD=admin
ports:
- "5432:5432"
volumes:
- data:/var/lib/postgresql/data
- ./database/1-schema.sql:/docker-entrypoint-initdb.d/01-schema.sql
- ./database/2-init.sql:/docker-entrypoint-initdb.d/02-init.sql
volumes:
data:
SQL脚本:
01-schema.sql
CREATE TABLE users ( id INTEGER PRIMARY KEY AUTOINCREMENT, username TEXT NOT NULL, );
02-init.sql
INSERT INTO users (username) VALUES ("John Doe"); INSERT INTO users (username) VALUES ("Jane Doe");
app.py
:
from flask import Flask import psycopg2 app = Flask(__name__) @app.route("/api") def index(): conn = psycopg2.connect("postgresql://postgres:admin@localhost:5432/postgres") cursor = conn.cursor() cursor.execute("SELECT * FROM users;") result = cursor.fetchone() conn.commit() conn.close() return result
当我运行docker-compose up
时,我收到以下错误消息:
psql:/docker-entrypoint-initdb.d/01-schema.sql: error: could not read from input file: Is a directory
exited with code 1
以下是完整的输出:
然后,当我尝试通过访问http://127.0.0.1:5000/api
来访问app.py
中的查询结果时,出现了一个错误,表示关系不存在:
数据库成功接收了查询,但也说关系不存在:
ERROR: relation "users" does not exist at character 15
STATEMENT: SELECT * FROM users;
答案:
以下是我项目的工作配置。
目录结构:
|-- .env |-- docker-compose.yaml |-- backend | |-- .env | |-- Dockerfile | |-- app.py | `-- dependencies.txt |-- database | |-- 01-schema.sql | |-- 02-init.sql | `-- Dockerfile `-- frontend |-- Dockerfile `-- (...Next.js应用程序文件)
docker-compose.yaml
:
services:
frontend:
container_name: frontend
build: ./frontend
image: node:18-alpine
restart: always
ports:
- "3000:3000"
volumes:
- ./frontend/:/app
- /app/node_modules
- /app/.next
backend:
container_name: backend
build: ./backend
image: flask:2.2.3
restart: always
ports:
- "5000:5000"
volumes:
- ./backend/:/backend
depends_on:
database:
condition: service_healthy
database:
container_name: database
build: ./database
image: postgres:15.2-alpine
restart: always
ports:
- "5432:5432"
volumes:
- data:/var/lib/postgresql/data
env_file:
- ./.env
healthcheck:
test:
["CMD", "pg_isready", "-U", "${POSTGRES_USER}", "-d", "${POSTGRES_DB}"]
interval: 5s
timeout: 10s
retries: 120
volumes:
data: null
Flask Dockerfile:
FROM python:3.11.2-slim-buster WORKDIR /backend ENV FLASK_APP app.py ENV FLASK_RUN_HOST 0.0.0.0 ENV FLASK_DEBUG 1 ENV PYTHONDONTWRITEBYTECODE 1 ENV PYTHONUNBUFFERED 1 COPY dependencies.txt . COPY .env . RUN pip install --upgrade pip && pip install -r dependencies.txt --no-cache-dir COPY . . CMD ["flask", "run"]
Database Dockerfile:
FROM postgres:15.2-alpine COPY ./*.sql /docker-entrypoint-initdb.d/
Frontend Dockerfile:
FROM node:18-alpine AS base # Install dependencies only when needed FROM base AS deps RUN apk add --no-cache libc6-compat WORKDIR /app COPY package.json package-lock.json ./ # Uncomment for production build # RUN npm install --omit=dev RUN npm install --legacy-peer-deps # Rebuild the source code only when needed FROM base AS builder WORKDIR /app COPY --from=deps /app/node_modules ./node_modules COPY . . ENV NEXT_TELEMETRY_DISABLED 1 RUN npm run build FROM base AS runner WORKDIR /app ENV NEXT_TELEMETRY_DISABLED 1 COPY --from=builder --chown=nextjs:nodejs /app/.next ./.next COPY --from=builder /app/node_modules ./node_modules COPY --from=builder /app/package.json ./package.json EXPOSE 3000 CMD ["npm", "start"]
.env
文件:
POSTGRES_DB=docker POSTGRES_USER=docker POSTGRES_PASSWORD=docker POSTGRES_HOST=database POSTGRES_PORT=5432
app.py
:
import psycopg2 # 注意:我使用python-dotenv加载环境变量 conn = psycopg2.connect( database=env.POSTGRES_DB, user=env.POSTGRES_USER, password=env.POSTGRES_PASSWORD, host=env.POSTGRES_HOST, port=env.POSTGRES_PORT, ) cur = conn.cursor() ...
dependencies.txt
:
flask psycopg2-binary python-dotenv
使用docker-compose up --build
构建容器,并使用docker-compose down --volumes
重置。使用docker-compose up
启动容器。
未解决的问题
- 我无法在不使用yarn的情况下使前端的热重载工作,这导致了一些问题。
- 我无法弄清楚如何使用Dockerfile中的
COPY
将主目录中的.env
文件复制到后端的容器中,所以我只是手动复制了一份。