728x90
반응형
SvelteKit과 Tailwind CSS에 대한 도커 이미지는 정상적으로 만들어졌지만, 컨테이너에 올려서 DB와 연결시키려고 하니
다음과 같은 에러가 나타났다.
app | Error fetching memo: MongoServerError: Authentication failed.
app | at Connection.sendCommand (/app/node_modules/mongoose/node_modules/mongodb/lib/
cmap/connection.js:297:27) mongo | {"t":{"$date":"2024-07-23T01:31:24.857+00:00"},"s":"
I", "c":"NETWORK", "id":22944, "ctx":"conn3","msg":"Connection ended","attr":{"remote":
"172.19.0.3:45378","uuid":{"uuid":{"$uuid":"ef48d134-dbb4-4ffa-842f-b164b2676dcc"}},"
connectionId":3,"connectionCount":0}} app | at process.processTicksAndRejections (node:
internal/process/task_queues:95:5) app | at async Connection.command (/app/node_modules
/mongoose/node_modules/mongodb/lib/cmap/connection.js:325:26) app | at async executeScr
am (/app/node_modules/mongoose/node_modules/mongodb/lib/cmap/auth/scram.js:79:22) app
| at async ScramSHA1.auth (/app/node_modules/mongoose/node_modules/mongodb/lib/cmap/aut
h/scram.js:39:16) app | at async performInitialHandshake (/app/node_modules/mongoose/n
ode_modules/mongodb/lib/cmap/connect.js:101:13) app | at async connect (/app/node_modul
es/mongoose/node_modules/mongodb/lib/cmap/connect.js:19:9) { app | errorResponse: { app
| ok: 0, app | errmsg: 'Authentication failed.', app | code: 18, app | codeName: 'Authe
nticationFailed' app | }, app | ok: 0, app | code: 18, app | codeName: 'AuthenticationF
ailed', app | connectionGeneration: 0, app | [Symbol(errorLabels)]: Set(2) { 'Handsha
keError', 'ResetPool' }
MONGODB_URI=mongodb://root:example@mongo:27017/memo_database
이런 식으로 루트의 username과 password를 사용하였지만 권한 부족이라고 에러가 떴기에 의아 했습니다.
원인과 해결법
MongoDB는 사용자를 생성할 때 특정 데이터베이스에 속한 사용자로 생성합니다. 기본적으로, admin 데이터베이스에 생성된 사용자는 모든 데이터베이스에 접근할 수 있는 권한을 가지지만, 다른 데이터베이스(memo_database등)에 사용자 정보를 저장하고 인증하려고 하면 admin 데이터베이스를 참조해야 합니다. 따라서 createUser로 한번 더 user를 만들어서 접속을 해야 합니다. 혹은 MongoDB에서 애플리케이션이 접근할 사용자 계정을 admin 데이터베이스가 아닌 애플리케이션이 실제로 접근하는 데이터베이스(memo_database)에 생성해야 합니다.
mongoDB에서 직접 createUser를 해도 되지만 init-mongo.js파일을 루트폴더에 만들어서 docker-compose.yml에서 활용할 수 있도록 하였습니다.
// init-mongo.js
db = db.getSiblingDB('memo_database');
db.createUser({
user: "memo_user",
pwd: "password123",
roles: [{ role: "readWrite", db: "memo_database" }]
});
# DockerFile
# 빌드 단계
FROM node:18-alpine AS builder
# 작업 디렉토리 생성
WORKDIR /app
# 소스 코드 복사
COPY . .
# 종속성 설치
RUN npm install
# TailwindCSS 빌드
RUN npx tailwindcss -i ./src/app.css -o ./static/build/tailwind.css
# 환경 변수 설정
COPY .env .env
RUN export $(cat .env | xargs) && npm run build
# 프로덕션 이미지
FROM node:18-alpine
# 작업 디렉토리 생성
WORKDIR /app
# 빌드된 파일 및 필요한 파일 복사
COPY --from=builder /app/build /app/build
COPY --from=builder /app/static /app/static
COPY --from=builder /app/package.json /app/package-lock.json /app/
# 프로덕션 종속성 설치
RUN npm install --production && \
npm cache clean --force
# 환경 변수 설정 (실행 단계)
ENV MONGODB_URI=mongodb://memo_user:1234@mongo:27017/memo_database
# 애플리케이션 실행
CMD ["node", "build/index.js"]
# docker-compose.yml
version: '3.8'
services:
mongo:
image: mongo:latest
container_name: mongo
ports:
- "27017:27017"
networks:
- app-network
environment:
MONGO_INITDB_ROOT_USERNAME: root
MONGO_INITDB_ROOT_PASSWORD: example
volumes:
- mongo-data:/data/db
- ./init-mongo.js:/docker-entrypoint-initdb.d/init-mongo.js:ro
app:
build: .
container_name: app
ports:
- "3000:3000"
networks:
- app-network
env_file:
- .env
depends_on:
- mongo
volumes:
mongo-data:
networks:
app-network:
driver: bridge
// database.js (mongoDB 연결하는 파일)
import mongoose from 'mongoose';
import dotenv from 'dotenv';
dotenv.config();
const MONGODB_URI = process.env.MONGODB_URI;
if (!MONGODB_URI) {
throw new Error('Please define the MONGODB_URI environment variable inside .env');
}
export async function connectToDatabase() {
if (mongoose.connection.readyState >= 1) return;
try {
await mongoose.connect(MONGODB_URI, {
useNewUrlParser: true,
useUnifiedTopology: true,
});
console.log('Successfully connected to MongoDB');
} catch (error) {
console.error('Error connecting to MongoDB:', error);
throw new Error('Failed to connect to MongoDB');
}
}
728x90
반응형