使用容器化的 Next.js + Flask + PostgreSQL 应用程序的问题

33 浏览
0 Comments

使用容器化的 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

以下是完整的输出:

Output-1

Output-2

然后,当我尝试通过访问http://127.0.0.1:5000/api来访问app.py中的查询结果时,出现了一个错误,表示关系不存在:

Flask Output

数据库成功接收了查询,但也说关系不存在:

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启动容器。

未解决的问题

  1. 我无法在不使用yarn的情况下使前端的热重载工作,这导致了一些问题。
  2. 我无法弄清楚如何使用Dockerfile中的COPY将主目录中的.env文件复制到后端的容器中,所以我只是手动复制了一份。
0
0 Comments

在创建一个包含Next.js、Flask和PostgreSQL的容器化应用程序时,出现了以下问题:

问题原因:

问题是由于compose文件中的一部分引起的。如果要挂载的文件不存在,Docker会在容器内创建一个空目录,导致错误信息显示为“是一个目录”。

解决方法:

1. 验证文件是否存在,路径是否正确,并尝试使用绝对路径替换相对路径。

2. 如果上述方法仍然不起作用,请尝试将整个目录挂载进去。

3. 尝试在dockerfile中添加文件,以查看是否以这种方式起作用。

4. 将迁移文件嵌入到镜像中,而不是在运行时挂载。

这是问题的解决方法,希望对其他遇到相同问题的人有所帮助。

0