Why this behaviour difference between docker run and docker-compose?

Hey everyone. I’m quite new to using docker and was experimenting with a NodeJS container connecting to a Mongodb container. I’m using mongoose for the connection. I tried this in two ways.

Method 1:

  • Setup a new docker network (docker network create mnet)
  • Create an image for the nodejs app using a Dockerfile.
  • Run a mongo container with username, password on mnet
  • Run a nodejs app container from created image on same mnet with credentials and mongo container name as env vars, to be used for connection.

index.js:

// env and connection only
const username = process.env.MUSER
const password = process.env.MPASS
const container = process.env.MCONT
const dbname = process.env.MDBNAME

mongoose.connect(`mongodb://${username}:${password}@${container}/${dbname}?retryWrites=true&writeConcern=majority&authSource=admin`
).then(() => {
    app.listen(port , () => {
        console.log('Server running')
    })
}).catch(err => console.log('Mongoose error ::: ', err))

Dockerfile:

FROM node:lts-alpine
WORKDIR /root/runtime
COPY package*.json ./
COPY index.js .
RUN npm install
CMD npm run app
EXPOSE 3000

docker run command:

docker run --name mint -e MONGO_INITDB_ROOT_USERNAME=admin -e MONGO_INITDB_ROOT_PASSWORD=mongo -p 27017:27017 -d --net mnet mongo

docker run --name eros -p 3000:3000 -e MUSER=admin -e MPASS=mongo -e MCONT=mint -e MDBNAME=testdb -d --net mnet napp

Method 2:

  • Write a docker compose file to create 2 services; one for mongo and one for nodejs app and network mnet.
  • docker-compose -f file.yaml up

index.js: same as method 1
Dockerfile: same as method 1

file.yaml:

version: '3'
services:
  mint:
    image: mongo
    container_name: mint
    ports:
      - '27017:27017'
    environment:
      - MONGO_INITDB_ROOT_USERNAME=admin
      - MONGO_INITDB_ROOT_PASSWORD=mongo
    networks:
      - mnet
  eros:
    build: .
    container_name: eros
    depends_on:
      - mint
    ports:
      - '3000:3000'
    environment:
      - MUSER=admin
      - MPASS=mongo
      - MCONT=mint
      - MDBNAME=testdb
    networks:
      - mnet
networks:
  mnet:

Method 1 worked perfectly but Method 2 keeps failing with “Authentication Failed” error. I am unable to understand why this happens. Maybe I’m not understanding the networking properly. Any help would make my day. Thank you for taking the time to read this.

Error:

Mongoose error :::  MongoServerError: Authentication failed.
eros1   |     at Connection.onMessage (/root/runtime/node_modules/mongodb/lib/cmap/connection.js:202:26)
eros1   |     at MessageStream.<anonymous> (/root/runtime/node_modules/mongodb/lib/cmap/connection.js:61:60)
eros1   |     at MessageStream.emit (node:events:514:28)
eros1   |     at processIncomingData (/root/runtime/node_modules/mongodb/lib/cmap/message_stream.js:124:16)
eros1   |     at MessageStream._write (/root/runtime/node_modules/mongodb/lib/cmap/message_stream.js:33:9)
eros1   |     at writeOrBuffer (node:internal/streams/writable:556:12)
eros1   |     at _write (node:internal/streams/writable:490:10)
eros1   |     at Writable.write (node:internal/streams/writable:494:10)
eros1   |     at Socket.ondata (node:internal/streams/readable:985:22)
eros1   |     at Socket.emit (node:events:514:28) {
eros1   |   ok: 0,
eros1   |   code: 18,
eros1   |   codeName: 'AuthenticationFailed',
eros1   |   connectionGeneration: 10,
eros1   |   [Symbol(errorLabels)]: Set(2) { 'HandshakeError', 'ResetPool' }
eros1   | }

Your compose file is an almost perfect translation of your docker run commands. Of course depends_on and build do not exist in docker run. But everything else is a 1:1 translation.

Usually when we see such a topic, users use arguments in their docker run commands that do not exist in the compose file, or have additional config items in their compose file that don’t exist as docker run argument.

Though, the one thing that I notice is that you use the deprecated docker-compose (=v1) command, instead of the docker compose (=v2) command. V2 will not care about the file schema version, and use the latest version.

You might want to try it again using docker compose.

1 Like

The category is Docker Desktop for Linux. Are you really using Docker Desktop? If you do, docker-compose is probably just an alias to docker compose, but it is better to check the version:

docker-compose version

I am using docker on Linux, but without the GUI. Thanks for the reply, will check it out.

Thank your. Will check this out.

You mean you didn’t install Docker Desktop or just don’t use the GUI of it?

How did you install Docker?

Have you tried to use the same image for the compose deployment, instead of building it? At least then its guaranteed that you test the same image, with the same container configuration:

services:
  # docker run -d \
  # --name mint \
  # -p 27017:27017 \
  # -e MONGO_INITDB_ROOT_USERNAME=admin \
  # -e MONGO_INITDB_ROOT_PASSWORD=mongo \
  # --net mnet \
  # mongo
  
  mint:
    image: mongo
    container_name: mint
    ports:
      - '27017:27017'
    environment:
      - MONGO_INITDB_ROOT_USERNAME=admin
      - MONGO_INITDB_ROOT_PASSWORD=mongo
    networks:
      - mnet

  # docker run -d \
  # --name eros \
  # -p 3000:3000 \
  # -e MUSER=admin \
  # -e MPASS=mongo \
  # -e MCONT=mint \
  # -e MDBNAME=testdb \
  # --net mnet \
  # napp

  eros:
    image: napp
    container_name: eros
    ports:
      - '3000:3000'
    environment:
      - MUSER=admin
      - MPASS=mongo
      - MCONT=mint
      - MDBNAME=testdb
    networks:
      - mnet
networks:
  mnet:

For a better comparability, I added the original docker run command, but ordered the arguments as they appear in the service, so it’s easier to compare it with the service configuration. Of course the compose file has no equivalent to -d and the image name at the end of the command becomes its own configuration item.

Using docker compose worked. Thank you!

Thanks for the detailed reply. Using docker compose instead of docker-compose worked. Not sure why tho.

Looks like I made a mistake. I’m using just the Docker Engine ( installed by following this Install Docker Engine on Ubuntu | Docker Docs ).