Passing command line arguments in Docker Compose

Is it possible to pass command line argument(s) into Docker Compose that can be used by the compose.yaml file? For example to set a build target in the compose.yaml file can I enter “dev” or “prod” from the Docker Compose command line? Currently I am using both a compose-dev.yaml file and a compose-prod.yaml file to get the results I want using a hard coded target: dev or target: prod. Would like to just use one compose.yaml file if possible. Thanks for looking.

Rick.

You can set environment variables.

MODE=prod docker compose up -d --build

Or

Create a .env file with the content

MODE=prod

and run

docker compose up -d --build

Or create two env files if you don’t want to change the content of a single file:

docker compose --env-file prod up --build
# or
docker compose --env-file dev up --build

“prod” and “dev” then must contain MODE=prod and MODE=dev

So you can use the variable in the compose file:

services:
  service:
    build:
      args:
        MODE: $MODE

Note that while --env-file passed to docker run sets the variables in the container, the same parameter passed to docker compose sets the variables to be used in the compose file.

1 Like

Thanks for the speedy reply. Here’s my current compose.yaml snippet:

services:
  server:
    build:
      args:
         MODE: $MODE
    context: .
    target: MODE

Then running “MODE=prod docker compose up -d --build

I get the following error message:

failed to solve: target stage MODE could not be found

Thanks for looking at this. Appreciate it. Rick.

Thank you for trying to make the code readable, however, you can use code blocks instead of non-breakable spaces. More details in the following guide: How to format your forum posts

In short, the icon (</>) is in the editor window above the text input.

Regarding your question, my example showed how you can pass variables to be used as build arguments (I answered quickly, sorry), but you can use the variable the same way for build target. If you look at your yaml you can notice the missing dollar sign, and if you don’t need it as a build argument, you can remove that part.

Very helpful. Thank you. Here’s my current snippet which works fine and lasts a long time.

services:
  server:
    build:
      context: .
      # MODE=[dev | prod] docker compose up -d --build 
      target: $MODE

Works well as contemplated with:
MODE=dev docker compose up -d --build
MODE=prod docker compose up -d --build

However, if I examine a couple of corner cases like:

  1. MODE=rick docker compose up -d --build, I get an expected error “failed to solve: target stage rick could not be found” OR

  2. if I just leave MODE out of the command line, l get an expected error “WARN[0000] The “MODE” variable is not set. Defaulting to a blank string.”

What would be the best practice for handling these cases?

'preciate you, rimelek
RIck.

Should that be found?

You can use the syntax similar to what you can use in bash:

services:
  server:
    build:
      context: .
      # MODE=[dev | prod] docker compose up -d --build 
      target: ${MODE:-prod}

That way “prod” will be the default

${MODE:-prod} … Groovy. Thanks. You save me a lot of time on this.

While I understand that "MODE=rick docker compose up -d --build should not be found, I am wondering if I can substitute my own error message for the default message “failed to solve: target stage rick could not be found”?

For example: “failed to solve: target stage rick could not be found. Use syntax MODE=[dev | prod] docker compose up -d --build" or something similar.

Rick.

No, there is no way to do that. You can create a wrapper script and run docker compose through that.

Ok. Thank you. I appreciate your prompt replies and help. Rick.