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?
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.)
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.