---
id: database-mongo
title: "MongoDB cho vận hành"
shortTitle: "MongoDB"
track: database
trackTitle: "Database"
order: 2
level: core
status: published
estimatedMinutes: 35
prerequisites:
  - database-postgres
next: database-sqlserver
reviewedAgainst: 2026-10-12
sources:
  - title: "MongoDB — built-in roles"
    url: https://www.mongodb.com/docs/manual/reference/built-in-roles/
  - title: "mongodump"
    url: https://www.mongodb.com/docs/database-tools/mongodump/
---

# MongoDB cho vận hành

Cùng việc với bài Postgres: user đủ quyền, dump, restore. Không thiết kế document. Lab dùng Docker, image `mongo:8`.

## Để làm gì

Tạo user cho app trên một database, dump database đó, restore sang tên khác. Đọc được connection string `mongodb://`.

## Gồm những gì

- User gắn với một database, role `readWrite`.
- `mongodump` và `mongorestore`.
- Vì sao không để Mongo mở không password ra Internet.

Không gồm replica set, sharding, hay cách viết query.

## Dùng khi nào

App dùng Mongo, hoặc một compose file có service `mongo`. Cassandra và DynamoDB là hai hệ khác. Cassandra thường ở hệ tự vận hành cluster lớn. DynamoDB là dịch vụ AWS, không có process `mongod` để dump bằng tool này.

## Kiến thức cốt lõi

User Mongo thuộc một database xác thực, thường là `admin` khi bạn tạo user quản trị. Role `readWrite` trên database `appdb` đủ để app đọc ghi database đó, không đủ để `dropDatabase` cả server. Docs built-in roles liệt kê `read`, `readWrite`, `dbAdmin`, `root`. App lấy `readWrite`. `root` chỉ để phá lab.

Connection string:

```text
mongodb://app:secret@127.0.0.1:27017/appdb?authSource=appdb
```

`authSource` là database chứa user. Tạo user trong `appdb` thì `authSource=appdb`. Tạo trong `admin` thì `authSource=admin`. Sai `authSource` thì báo authentication failed dù password đúng.

`mongodump --archive` ghi một file. `mongorestore --nsFrom` và `--nsTo` đổi tên database lúc restore. Không có hai flag đó thì restore đè đúng tên cũ.

Image `mongo` chính thức không bật auth cho đến khi bạn tạo user và chạy với `mongod --auth`, hoặc đặt `MONGO_INITDB_ROOT_USERNAME`. Lab đặt root user qua biến môi trường để auth bật từ đầu.

## Lệnh và code mẫu

```bash
docker run -d --name lab-mongo \
  -e MONGO_INITDB_ROOT_USERNAME=root \
  -e MONGO_INITDB_ROOT_PASSWORD=lab \
  -p 27017:27017 \
  mongo:8
```

Đợi container healthy. Tạo user app:

```bash
docker exec lab-mongo mongosh -u root -p lab --authenticationDatabase admin --eval '
  db.getSiblingDB("appdb").createUser({
    user: "app",
    pwd: "secret",
    roles: [{ role: "readWrite", db: "appdb" }]
  })
'
```

Ghi một document bằng user app, rồi dump:

```bash
docker exec lab-mongo mongosh "mongodb://app:secret@127.0.0.1:27017/appdb?authSource=appdb" --eval '
  db.orders.insertOne({ sku: "a1", qty: 1 })
'
docker exec lab-mongo mongodump \
  --uri "mongodb://app:secret@127.0.0.1:27017/appdb?authSource=appdb" \
  --archive=/tmp/app.archive
docker cp lab-mongo:/tmp/app.archive "$HOME/devops-lab/database/app.archive"
```

## Thực hành

1. Chạy container và `createUser`.
2. Insert một document. `find` lại phải thấy `sku: "a1"`.
3. Dump ra archive và `docker cp` về máy.
4. Thử connect không password: `mongosh mongodb://127.0.0.1:27017/appdb`. Phải bị từ chối.
5. `docker rm -f lab-mongo` khi xong.

## Kết quả mong đợi

- User `app` ghi được vào `appdb`.
- File `app.archive` có kích thước lớn hơn 0.
- Connection không password thất bại.
- Port 27017 không còn sau khi xoá container.

## Checklist

- [ ] App dùng `readWrite` trên đúng database, không dùng `root`.
- [ ] Connection string có `authSource` trùng nơi tạo user.
- [ ] Dump bằng `mongodump`, không copy raw file trong `/data/db` khi server đang chạy.
- [ ] Không publish port Mongo ra Internet nếu chưa bật auth.

## Lỗi thường gặp

**`authentication failed` dù password đúng.** `authSource` sai database. Nhìn lại `createUser` chạy trên database nào.

**Copy thư mục data của container đang chạy rồi gọi đó là backup.** File có thể dở. Dùng `mongodump`, hoặc filesystem snapshot theo docs Mongo, không `docker cp` data dir lúc đang ghi.

**Mở port 27017 với image không đặt `MONGO_INITDB_ROOT_USERNAME`.** Bản mặc định không auth. Bot quét port này. Lab nào xong thì `docker rm -f`.

## Nguồn

1. [Built-in roles](https://www.mongodb.com/docs/manual/reference/built-in-roles/) — MongoDB, `readWrite` và `root`.
2. [mongodump](https://www.mongodb.com/docs/database-tools/mongodump/) — archive và URI.

## Tiếp theo

[SQL Server](./03-sqlserver.md)
