6

I have a docker-compose.yml file, and in that a build context for a given service with a Dockerfile.

Sample docker-compose:

version: '3' services: scd-service: build: context: ./cmd/some-service/ dockerfile: Dockerfile args: broker: redis:6379 queue: somequeue depends_on: - redis networks: - backend redis: image: "redis:alpine" restart: unless-stopped networks: - backend 

It can find the Dockerfile and build it with: docker-compose up --build some-service

However, this will fail. The broker and queue args are never passed to the given Dockerfile.

Sample Dockerfile:

FROM golang:1.11 // stuff... ARG broker ARG queue CMD ["go", "run", "/go/src/github.com/org/project/cmd/some-service/some-service.go", "--broker $broker", "--queue $queue"] 

As evident in the build stage, these are never parsed:

Step 7/7 : CMD ["go", "run", "/go/src/github.com/org/project/cmd/some-service/some-service.go", "--broker $broker", "--queue $queue"] 

Whereafter the Go program crashes as the command line parameters are invalid.

How does one parse args from docker-compose to a Dockerfile?

Edit: Weirdly, I can echo the correct value?

Example:

ARG broker ARG queue RUN echo ${broker} 

Outputs:

Step 7/8 : RUN echo ${broker} ---> Running in c84828847d9a redis:6379 

How is this not parsed onto the CMD?

1
  • 2
    Build-args are only available at build-time, but CMD entry executes at run-time. Here's a reference and a possible solution: stackoverflow.com/questions/35560894/… Commented Jun 11, 2019 at 13:07

2 Answers 2

11

There are two problems here. ARG is only used at build time, when creating the image, and CMD defines a step at run time, when running your container. ARG gets implemented as an environment variable for RUN steps, so it is up to the shell to expand the environment variable. And the json syntax doesn't run a shell. So to do this with CMD, you need to make two changes.

First, you need to save your ARG as an ENV value that gets saved to the image metadata and used to setup the environment when creating the container.

And second, you need to switch from an exec/json syntax for running CMD to run a shell that will expand these variables. Docker does this for you with the string syntax.

The end result looks like:

FROM golang:1.11 // stuff... ARG broker ENV broker=${broker} ARG queue ENV queue=${queue} CMD go run /go/src/github.com/org/project/cmd/some-service/some-service.go --broker "$broker" --queue "$queue" 

As an aside, you should also note that every argument in exec syntax needs to be a separate array entry, e.g.:

CMD ["go", "run", "/go/src/github.com/org/project/cmd/some-service/some-service.go", "--broker $broker", "--queue $queue"] 

is similar to running:

go run /go/src/github.com/org/project/cmd/some-service/some-service.go "--broker $broker" "--queue $queue" 

when you really wanted to run:

CMD ["go", "run", "/go/src/github.com/org/project/cmd/some-service/some-service.go", "--broker", "your_broker", "--queue", "your_queue"] 

which would be similar to:

go run /go/src/github.com/org/project/cmd/some-service/some-service.go --broker "your_broker" --queue "your_queue" 

(Note I removed the variables from my example because they do not work in the exec syntax.)

Sign up to request clarification or add additional context in comments.

3 Comments

Thanks for your help. Seems like the container cannot see the redis container otherwise specified now, but one problem at a time. Cheers, it worked.
ARG can be used during BUILD time as well as during RUN time but it needs to be declared as mentioned in the docs: docs.docker.com/engine/reference/builder/…
@AshishSingh the RUN step is performed at build time, when you create the image. The CMD step is executed at runtime, when you create the container. Yes the terminology is a bit confusing.
4

You should set them as ENV, if you want them to be avaliable on containers based on the image (running-side). Something like:

ENV broker $broker //assign your env broker value to container ENV queue $queue 

ARG

These are avaliable when you create the image, but not when you want to run a container based on that.

ENV

ENV values are available to containers and also RUN-style commands. If you want the arguments to be avaliable during runtime, these are the good ones.

You also may find useful info about env values here.

Edit. In order to avoid [Warning] One or more build-args [] were not consumed message, you should do something like:

ARG broker=your.broker.value ENV broker=${broker} 

The error is telling that you have unused ARGS (altough you may be ok without setting them now that you have ENVs). More info here as well.

5 Comments

Can you provide an example? Just swapping out ARG with ENV appears to be invalid syntax.
sure! it's a silly example, but the provided link may guide you better : )
With your example, I get: [Warning] One or more build-args [queue broker] were not consumed
Edited, that seems to be related to not-using the args you provide (silly docker)
What is your.broker.value referring to? This is what should be passed on from docker-compose, presumably?

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.