compose: Undefined default build arg is sent as empty string to docker build, instead of not sent
In issue #3281 compose < 1.8.0-rc1
incorrectly sent undefined default build args as 'None'
string to docker build
, it was fixed by PR #3449 (included in compose 1.8.0-rc1
) by sending an empty string instead to docker build
.
I think it would be better to just not send the undefined build args to docker build
, so that the default value for the build arg defined in Dockerfile
would apply.
Scenario:
Files
Dockerfile
:
FROM ubuntu:14.04
ARG FOO=1
RUN echo "-${FOO}-"
CMD /bin/bash
docker-compose.yml
:
version: '2'
services:
test:
build:
context: .
args:
- FOO
Execution:
$ ./docker-compose-1.8.0-rc1 --verbose config
networks: {}
services:
test:
build:
args:
FOO: ''
context: /home/riccardi/git/ses-docker/test-default-build-arg
version: '2.0'
volumes: {}
$ ./docker-compose-1.8.0-rc1 --verbose build
compose.config.config.find: Using configuration files: ./docker-compose.yml
docker.auth.auth.load_config: Found 'auths' section
docker.auth.auth.parse_auth: Found entry (registry=u'docker-registry-stag.systran.net:5000', username=u'systran')
compose.cli.command.get_client: docker-compose version 1.8.0-rc1, build 9bf6bc6
docker-py version: 1.8.1
CPython version: 2.7.9
OpenSSL version: OpenSSL 1.0.1e 11 Feb 2013
compose.cli.command.get_client: Docker base_url: http+docker://localunixsocket
compose.cli.command.get_client: Docker version: KernelVersion=4.4.0-21-generic, Os=linux, BuildTime=2016-04-26T23:30:23.291099901+00:00, ApiVersion=1.23, Version=1.11.1, GitCommit=5604cbe, Arch=amd64, GoVersion=go1.5.4
compose.service.build: Building test
compose.cli.verbose_proxy.proxy_callable: docker build <- (pull=False, stream=True, nocache=False, tag=u'testdefaultbuildarg_test', buildargs={u'FOO': ''}, rm=True, forcerm=False, path='/home/riccardi/git/ses-docker/test-default-build-arg', dockerfile=None)
docker.api.build._set_auth_headers: Looking for auth config
docker.api.build._set_auth_headers: Sending auth config (u'docker-registry-stag.systran.net:5000')
compose.cli.verbose_proxy.proxy_callable: docker build -> <generator object _stream_helper at 0x7f8a18739b40>
Step 1 : FROM ubuntu:14.04
---> 8f1bd21bd25c
Step 2 : ARG FOO=1
---> Using cache
---> a8c68a88ef6d
Step 3 : RUN echo "-${FOO}-"
---> Running in c03d7e477353
--
---> 17f6ac07ea06
Removing intermediate container c03d7e477353
Step 4 : CMD /bin/bash
---> Running in 47164716758d
---> 5ef78af6532b
Removing intermediate container 47164716758d
Successfully built 5ef78af6532b
compose.cli.verbose_proxy.proxy_callable: docker close <- ()
compose.cli.verbose_proxy.proxy_callable: docker close -> None
Issue
Expected result:
prints -1-
.
Actual result:
prints --
.
<1.8.0-rc1
result:
prints -None-
.
Details
compose 1.8.0-rc1
behavior is better than previous compose
versions: it could be accepted as a correct behavior.
However, I believe the behavior could be improved further by expecting -1-
as result, not --
: if docker compose has no value for the build arg, then it should let docker build
apply its own default value that comes from the Dockerfile
.
Changing from --
to -1-
is a breaking change, so I suggest to release it in 1.8.0 if this behavior is accepted.
Without this feature, I have to duplicate the default value both in Dockerfile
and in .env
read by docker-compose
(or just in .env
, but in this case the Dockerfile
cannot be used alone, without docker-compose
), and I think the best place for the default value is in the Dockerfile
only.
About this issue
- Original URL
- State: closed
- Created 8 years ago
- Reactions: 10
- Comments: 33
Commits related to this issue
- Unset default value for FAIL_ON_TEST_FAILURE as unsetting it via --build-arg seems unreliable https://github.com/docker/compose/issues/3608 — committed to ros-planning/navigation2 by ruffsl a year ago
- Patch CI actions and Dockerfiles (#3468) * Unset default value for FAIL_ON_TEST_FAILURE as unsetting it via --build-arg seems unreliable https://github.com/docker/compose/issues/3608 * Use build... — committed to ros-planning/navigation2 by ruffsl a year ago
- fix: docker-compose mandates COMMIT_HASH arg https://github.com/docker/compose/issues/3608#issuecomment-515715656 — committed to y-young/f1music by y-young a year ago
- Patch CI actions and Dockerfiles (#3468) * Unset default value for FAIL_ON_TEST_FAILURE as unsetting it via --build-arg seems unreliable https://github.com/docker/compose/issues/3608 * Use build... — committed to ros-planning/navigation2 by ruffsl a year ago
- Humble sync 6 June 9: 1.1.7 (#3616) * Option allowing to use simple lookupTransform API (#3412) * Option allowing to use simple lookupTransform API ignoring time shifts between source and base fr... — committed to ros-planning/navigation2 by SteveMacenski a year ago
- Humble sync 6 June 9: 1.1.7 (#3616) * Option allowing to use simple lookupTransform API (#3412) * Option allowing to use simple lookupTransform API ignoring time shifts between source and base frame... — committed to EnjoyRobotics/navigation2 by SteveMacenski a year ago
- Nav2 Sync 1 Oct 18 (#8) * Update nav2_multirobot_params_2.yaml * Update nav2_multirobot_params_1.yaml * Humble backport of MPPI controller (#3439) * Adding new MPPI controller to Nav2 (#3350... — committed to EnjoyRobotics/navigation2 by RBT22 8 months ago
- Nav2 Sync 1 Oct 18 (#8) * Update nav2_multirobot_params_2.yaml * Update nav2_multirobot_params_1.yaml * Humble backport of MPPI controller (#3439) * Adding new MPPI controller to Nav2 (#3350... — committed to EnjoyRobotics/navigation2 by RBT22 8 months ago
I’ve encountered this impacting use of proxy related variables, and part of the it is that the behaviour between args and environment is not consistent.
Reading https://docs.docker.com/compose/compose-file/#/args and https://docs.docker.com/compose/compose-file/#/environment, one would expect the same behaviour from both.
Given a service defined as follows:
If you happen to only have http_proxy & https_proxy defined but not HTTP_PROXY & HTTPS_PROXY defined what you will see during the build is that HTTP_PROXY and HTTPS_PROXY are set to ‘’, which causes anything checking the environment for these variables to assume that their existance means no proxy is defined, rather than moving onto checking the lowercase versions as well.
This can cause all sorts of opaque issues building with docker-compose behind proxies because the behaviour for the environment versions of these is different. I’ve discovered that apk will not check for http_proxy if it finds HTTP_PROXY set to an empty string.
You could argue the software should check for both variations, however given the difference in behavour when dealing with environment settings, such as if you have an image built, and using the same unset/set variables listed above, and run
docker-compose run -u root jenkins env
you will not see HTTP_PROXY or HTTPS_PROXY appearing in the output.This is because for environment:
SOMEVAR is considered optional, and is only picked up from the environment of the user if defined.
It seems like it would be much better to have the behaviour of args and environment consistent, and since environment has been around for longer, I would suggest that following it’s behaviour rather than changing environment to follow the newer behaviour of args will have less of an impact.
Perhaps it would be better if instead of having:
pass through a variable as being empty, require that someone provide ‘=’, with nothing after it to indicate that it’s intended to override with an empty value.
This would match the existing behaviour for environment, and avoid surprising behaviour.
Override SOMEVAR in Dockerfile only if defined in user environment:
OR
Override SOMEVAR in Dockerfile with blank value
or
Override SOMEVAR in Dockerfile with different value
or
This seems to give the flexibility needed to be able to override with blank values, while also retaining the ability to pass through certain env variables only if set.
AFAIK the problem still exists and is why I’ve had to avoid docker compose for building of images due to the inconsistency
Let’s create activity here to keep the issue open, because I assume the issue is still there if no compose developer talked about it here, and we have recent documented workarounds…
Something like this would be amazing:
This is a real issue that needs to be resolved
FIve years 😢 With this, and no support for build time secrets, docker-compose is more of a headache than it is useful!
One thing that might help is if a maintainer could confirm if any of the proposed behaviour changes would be acceptable if a PR was put together?
This issue does not have a true workaround. The workarounds presented do not solve the core issue as requested by @thomas-riccardi :
The workaround given by @idetoile does not work for ARGs. They still behave as when this issue was first open, regardless of having been able to use bash inline defaults.
Furthermore, use of bash inline defaults are documented nowhere, apart from being nonchalantly glossed over in the section on Scope for ARGs in Dockerfile reference, so this particular issue is the documentation for the matter, which also adds to the frustration.
Anyway,
Given compose file:
and Dockerfile:
Issuing
docker build --build-arg FOO --no-cache .
Results in the relevant lines being:
Whereas running
docker-compose build
results in:Which means that the 2017 merge of PR to @thomas-riccardi issue in docker upstream solved this issue in docker itself, but compose still does something wrong when passing the argument.
FOO=
andFOO
are not the same thing, if you want to overrideARG FOO=1
from theDockerfile
with empty string, you can either putargs: [ FOO= ]
in thedocker-compose.yml
, or in the.env
, so I don’t see any issue here.However, your 3rd point is valid: indeed, docker engine treats
--build-arg FOO
as--build-arg FOO=
ifFOO
is not defined in thedocker build
process environment.I understand your point about keeping the same behavior on both
engine
andcompose
. I’ll open an issue in docker engine for that.I’d like to point out that this docker engine feature is not documented anywhere (neither in https://docs.docker.com/engine/reference/commandline/build/, nor in https://docs.docker.com/engine/reference/builder/). I suggest to not document it for compose either so it’ll be easier to change the behavior without it being considered as a breaking change.
Thanks
PS: maybe this issue can be closed for now; I’m not sure what procedure to follow in this case.
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.
My workaround example:
with this implementation I need to define default version only in Dockerfile, and my docker-compose file is proxying ARG from optional env var
@agilgur5 I like your
docker-compose build myservice --build-arg MYBUILDARG=argggg
idea! You probably should open a new issue for that.