admin管理员组文章数量:1122846
I'm building a Next.js 14 app running in a Docker container where users can upload images. These images are stored outside the public folder in Server/uploads (shared via Samba on my home server), and I need them to be immediately available during runtime without having to rebuild the app. I'm using Apache as a reverse proxy to serve the images, but when trying to access them, I get a 404 error even though I see the image get successfully uploaded to the correct folder.
Image Upload Route:
// Set the base upload directory on the server-side
const baseUploadPath = path.join(__dirname, "../uploads");
if (!fs.existsSync(baseUploadPath)) {
fs.mkdirSync(baseUploadPath, { recursive: true });
}
// Multer storage setup for image uploads
const storage = multer.diskStorage({
destination: (req, file, cb) => {
const userUploadPath = path.join(baseUploadPath, req.user.id.toString()); // Create user-specific folder
if (!fs.existsSync(userUploadPath)) {
fs.mkdirSync(userUploadPath, { recursive: true });
}
cb(null, userUploadPath); // Save to user-specific folder
},
filename: (req, file, cb) => {
cb(null, Date.now() + "-" + file.originalname); // Unique filename
},
});
const upload = multer({ storage });
// Create a new spot (Protected Route)
router.post("/", authMiddleware, upload.single("image"), async (req, res) => {
try {
const { spotName, description, location } = req.body;
// Ensure location exists and split into latitude and longitude
if (!location) {
return res.status(400).json({
message:
"Location is required and should be in 'latitude, longitude' format.",
});
}
const [latitude, longitude] = location
.split(",")
.map((coord) => parseFloat(coord.trim()));
if (isNaN(latitude) || isNaN(longitude)) {
return res.status(400).json({
message: "Invalid coordinates format. Use 'latitude, longitude'.",
});
}
// Generate the relative path for the image (e.g., /uploads/userId/image.jpg)
const imagePath = req.file
? `/uploads/${req.user.id}/${req.file.filename}`
: null;
// Create the new spot
const newSpot = await Spot.create({
spotName,
description,
location,
latitude,
longitude,
image: imagePath,
userId: req.user.id, // Authenticated user ID
});
res.status(201).json(newSpot);
} catch (error) {
res.status(500).json({ message: "Failed to add the spot" });
}
});
Here is my apache2 conf file:
<VirtualHost *:80>
ServerName caligo.site
ServerAlias www.caligo.site
ProxyPreserveHost On
# Update all backend routes to include /api prefix
ProxyPass "/api/auth" "http://localhost:3001/api/auth"
ProxyPassReverse "/api/auth" "http://localhost:3001/api/auth"
ProxyPass "/api/comments" "http://localhost:3001/api/comments"
ProxyPassReverse "/api/comments" "http://localhost:3001/api/comments"
ProxyPass "/api/spots" "http://localhost:3001/api/spots"
ProxyPassReverse "/api/spots" "http://localhost:3001/api/spots"
ProxyPass "/api/users" "http://localhost:3001/api/users"
ProxyPassReverse "/api/users" "http://localhost:3001/api/users"
# Serve the uploads directory directly
Alias "/uploads" "/home/sambauser/shared_folder/web servers/CaliGo/Server/uploads"
<Directory "/home/sambauser/shared_folder/web servers/CaliGo/Server/uploads">
Options Indexes FollowSymLinks
AllowOverride None
Require all granted
</Directory>
EnableMMAP off
# Route all other paths to frontend on port 3000
ProxyPass "/" "http://localhost:3000/"
ProxyPassReverse "/" "http://localhost:3000/"
</VirtualHost>
Issues:
- The uploaded images are not accessible via the /uploads route and result in a 404 error.
- The files are stored on my home server using Samba for file sharing, and the Apache server is configured to serve them.
Here is my Dockerfile in my client folder:
# Dockerfile for Next.js frontend
# Use the official Node.js image
FROM node:18-alpine
# Set the working directory
WORKDIR /app
# Set environment variable for production
ENV NODE_ENV=production
# Copy package.json and package-lock.json
COPY package*.json ./
# Install dependencies
RUN npm install
# Copy the rest of the application code
COPY . .
# Build the Next.js app
RUN npm run build
# Expose the port Next.js runs on
EXPOSE 3000
# Start the Next.js app
CMD ["npm", "start"]
And here is my Server Dockerfile:
# Dockerfile for Node.js backend
FROM node:18-alpine
# Install dependencies for bcrypt on Alpine
RUN apk add --no-cache python3 make g++
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
# Expose the backend port
EXPOSE 3001
# Wait for MySQL to be available, then start the server
CMD /bin/sh -c "while ! nc -z mysql 3306; do echo 'Waiting for MySQL...'; sleep 3; done && node server.js"
Finally here's my docker-compose file:
version: "3.8"
services:
frontend:
build:
context: ./client
dockerfile: Dockerfile
ports:
- "3000:3000"
env_file:
- .env # Use .env for environment variables
depends_on:
- backend
volumes:
- ./client/public:/app/public # Map the frontend public folder for static assets
mysql:
image: mysql:8.0
environment:
MYSQL_DATABASE: db
MYSQL_ROOT_PASSWORD: password
volumes:
- mysql_data:/var/lib/mysql # Persistent storage for MySQL database
ports:
- "3307:3306"
backend:
build:
context: ./Server
dockerfile: Dockerfile
ports:
- "3001:3001"
env_file:
- .env # Use .env for environment variables
volumes:
- ./Server/uploads:/app/uploads # Persistent storage for uploaded images in backend
depends_on:
- mysql
volumes:
mysql_data: # Persistent storage for MySQL data
What I've tried:
- Ensuring that the file permissions are correct on the uploads directory.
- Testing the route with direct access to the images outside the container, which also results in a 404 error.
Additional Info:
- The app is running on a home server using Samba for file sharing.
- Apache is configured as a reverse proxy to serve the frontend and backend.
- The images are stored outside the Next.js public folder but are being uploaded to the server's uploads directory, which is shared via Samba.
本文标签: docker404 Error when Serving Files Outside of public Directory in Nextjs 14Stack Overflow
版权声明:本文标题:docker - 404 Error when Serving Files Outside of public Directory in Next.js 14 - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1736299973a1930648.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论