Skip to content

MongoDB ​

UseImageStatus
MongoDBmongo:9.0.2-nobledefault
MongoDBmongo:8.0.32-nobleallowed (N-1)

Pinned, as every compose file and Dockerfile writes them:

text
mongo:9.0.2-noble@sha256:61dd87ff554dc20386c63ebe1f7ede27314370ad5a7bf357c685fab424672158
mongo:8.0.32-noble@sha256:0393ab544cbbe92b2dd64719205ecb14a8b3824b17ea75051e2f22482c3e4e66

The tags and digests come from the approved images table; when they disagree, the table wins. MongoDB publishes no Debian variant: -noble is Ubuntu 24.04, the glibc choice, for the same reason as the rest (see rule 4).

Local development ​

docker run
sh
docker run -d --name mongo-dev \
  -p 127.0.0.1:27017:27017 \
  -e MONGO_INITDB_ROOT_USERNAME=admin -e MONGO_INITDB_ROOT_PASSWORD=dev \
  -v mongo-dev-data:/data/db \
  --health-cmd 'mongosh --quiet --eval "db.adminCommand({ping: 1}).ok" | grep -q 1' \
  --health-interval 5s --health-timeout 10s --health-retries 12 \
  mongo:9.0.2-noble@sha256:61dd87ff554dc20386c63ebe1f7ede27314370ad5a7bf357c685fab424672158
check docker run
sh
docker exec mongo-dev mongosh --quiet -u admin -p dev --eval 'db.runCommand({buildInfo: 1}).version'

Connect with mongodb://admin:dev@127.0.0.1:27017/?authSource=admin. Remove it, data included, with docker rm -f mongo-dev && docker volume rm mongo-dev-data.

On a new kernel ​

MongoDB 8.0 and later refuse to start on Linux 6.19 and newer, with "MongoDB cannot start: Linux kernel versions 6.19 and newer has a known incompatibility" (SERVER-121912). The cause is TCMalloc, inside MongoDB, breaking the kernel's rseq ABI; there is no fixed release yet, and the GLIBC_TUNABLES workaround does not help. Check with uname -r.

  • Servers run an LTS kernel (Ubuntu 24.04 ships 6.8), which is not affected. Do not move a MongoDB host to a 6.19+ kernel until a fixed release is in the table.
  • A developer machine on 6.19+ cannot run these images locally. Run MongoDB on a server, or in a VM with an older kernel, until MongoDB ships a fix.

On a server ​

Prepare the host once, next to the compose file. The root password is a file the container reads on its first start, never an environment value that docker inspect shows.

prepare the host
sh
mkdir -p secrets
openssl rand -hex 24 > secrets/mongo_root_password
sudo chown 999:999 secrets/mongo_root_password
sudo chmod 0400 secrets/mongo_root_password
compose.yml
yaml
services:
  mongo:
    image: mongo:9.0.2-noble@sha256:61dd87ff554dc20386c63ebe1f7ede27314370ad5a7bf357c685fab424672158
    environment:
      MONGO_INITDB_ROOT_USERNAME: admin
      MONGO_INITDB_ROOT_PASSWORD_FILE: /run/secrets/mongo_root_password
    secrets: [mongo_root_password]
    volumes:
      - mongo-data:/data/db
      - mongo-config:/data/configdb
    ports:
      - "127.0.0.1:27017:27017"
    read_only: true
    tmpfs:
      - /tmp:size=64m,mode=1777
    cap_drop: [ALL]
    cap_add: [CHOWN, DAC_READ_SEARCH, SETGID, SETUID]
    security_opt:
      - no-new-privileges:true
    healthcheck:
      test: ["CMD-SHELL", "mongosh --quiet --eval 'db.adminCommand({ping: 1}).ok' | grep -q 1"]
      interval: 10s
      timeout: 10s
      retries: 5
      start_period: 30s
    stop_grace_period: 1m
    restart: unless-stopped
    logging:
      driver: json-file
      options:
        max-size: "10m"
        max-file: "3"

volumes:
  mongo-data: {}
  mongo-config: {}

secrets:
  mongo_root_password:
    file: ./secrets/mongo_root_password
check compose
sh
docker compose exec mongo sh -c 'mongosh --quiet -u admin -p "$(cat /run/secrets/mongo_root_password)" --eval "db.runCommand({buildInfo: 1}).version"'

The root user is for administration only. Create a user per service with access to its own database, and give the service that user in its .env, as mongodb://<user>:<password>@mongo:27017/<db>?authSource=<db>.

Why each line is there:

  • The root password is read once. MONGO_INITDB_* applies only when /data/db is empty; changing the file later changes nothing. Rotate it with db.changeUserPassword instead.
  • /data/configdb is a volume too. The image declares it, and an anonymous volume would be lost on the next docker compose down.
  • The health check pings without logging in. ping needs no authentication, so the check never needs the password.
  • The capabilities. The entrypoint starts as root, fixes the data folders' owner and drops to the mongodb user (999); these three are what that needs.
  • read_only. MongoDB writes only to its two volumes and its socket in /tmp.
  • stop_grace_period: 1m. A clean shutdown flushes the journal; a kill makes the next start recover it.
  • Port on 127.0.0.1. Never publish MongoDB on 0.0.0.0.

Upgrading ​

Default 9.0, allowed 8.0; anything older moves to 8.0 first.

Upgrade one major at a time (7.0 to 8.0 to 9.0), and set the feature compatibility version after each step, once the new major runs cleanly:

js
db.adminCommand({ setFeatureCompatibilityVersion: "8.0", confirm: true })

A new major cannot start on data whose feature compatibility version is two majors behind. Take a mongodump before each step.