Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add TAG command to Dockerfile #5603

Closed
matthewcmorgan opened this issue May 5, 2014 · 38 comments
Closed

Add TAG command to Dockerfile #5603

matthewcmorgan opened this issue May 5, 2014 · 38 comments
Labels
area/builder kind/feature Functionality or other elements that the project doesn't currently have. Features are new and shiny

Comments

@matthewcmorgan
Copy link

Like the MAINTAINER command, a TAG command would allow a Dockerfile to record the intended destination for a container after a build. When doing a docker build from command line, the TAG command would allow a default -t mytag/mycontainer to be used. If docker build is passed a different -t mytag/mycontainer then it would overwrite the TAG command in the dockerfile.

This would be especially useful for those of us using a private docker registry so we can see what others tagged a built container as when it was pushed to a private registry.

@cyphar
Copy link
Contributor

cyphar commented May 6, 2014

  • What happens if there are multiple TAG instructions?
  • Should you be able to make an untagged build if it contains a TAG instruction?

Also, when you said "destination for a container after a build", did you mean "the tag for a container after a build"?

@matthewcmorgan
Copy link
Author

  • What happens if there are multiple TAG instructions?

For this, I would have to ask how does the cli handle passing it multiple -t myregistry/mycontainer parameters? And that is, it creates multiple images with the various tags. I don't see any reason not to continue the same behaviour by allowing the TAG command to happen in the Dockerfile. I suppose that would change my previous suggestion of having a cli passed -t command override the included TAG command in a Dockerfile.

  • Should you be able to make an untagged build if it contains a TAG instruction?

This one is a little bit trickier. I suppose we'd have to ask for the purpose of an untagged build. Seeing as an untagged build can't be pushed to a registry, I would question the usefulness. I suppose we could refer to the answer of the previous question and respond with "why not both?" That is to say, we could create both an untagged container and a tagged container by default, seeing as docker build with multiple -t creates multiple tagged builds that are identical.

  • Also, when you said "destination for a container after a build", did you mean "the tag for a container after a build"?

I would suggest this is semantics. The Tag for a container implicitly implies the destination registry and the name of the container when stored on that registry, so both statements are accurate. In the context of my original comment, I intended it to mean destination, as I deal with multiple private registries and keeping the containers aligned with their destination registry is sometimes more complex than necessary.

@ewindisch
Copy link
Contributor

Could be okay if we restricted this to a specific namespace such as "my-user/$TAG". Then, with signing and trust coming down the line, it would be signed by "my-user".

Still, some important considerations need to be made on the security, trust, and distribution angles.

@thaJeztah
Copy link
Member

I like this idea.

What happens if there are multiple TAG instructions?

Each TAG instruction could tag the current layer/container as a new image. This would allow to;

  • Create multiple images from a single Dockerfile
  • Create different tags for the same image

For example:

FROM debian

RUN apt-get update

RUN apt-get install -y apache

COPY ./start-apache.sh /start/sh
CMD ["/start.sh"]

TAG myname/apache

RUN apt-get install -y php5

TAG myname/apache-php:latest
TAG myname/apache-php:1.0.1

Which would result in three images; myname/apache:latest, myname/apache-php:latest and myname/apache-php:1.0.1.

The last two tags would be pointing to the same image.

_Overriding_

If a tag is provided on the command-line, all tags in the Dockerfile should be ignored.

Again, using the Dockerfile above, this;

docker build -t myname/apache-test .

Should result in a single tagged image (myname/apache-test) from the final result of the Dockerfile build.

@cxmcc
Copy link
Contributor

cxmcc commented Sep 26, 2014

@matthewcmorgan by saying "container" in the original post I think you mean "image" instead.

Yes I have the exactly same idea.

@KyleAMathews
Copy link

Please someone do this. Not having this hurts my ability to use images from the Trusted Build as I can't run specific versions of say MySQL. This introduces a lot of uncertainty as I'm never sure what I'm getting when use a community provided image.

@jessfraz
Copy link
Contributor

@KyleAMathews Do you mean in your dockerfile? You can use FROM mysql:tag

@KyleAMathews
Copy link

No, set the tag for the eventual image.

E.g. you're building MySQL 5.6.1 so you'd add something like TAG 5.6.1

@josephpage
Copy link

Not seems like a good idea to me : tags are not persistent across nested images.

Already discussed here #886 and closed. @crosbymichael

@xuxinkun
Copy link

xuxinkun commented May 5, 2015

As @thaJeztah say, I think TAG instruction is necessary for Dockerfile to create multiple images from a single Dockerfile and create different tags for the same image. So, I make this pull requst #12983 .
But I don't think it is an good idea for Overriding. So even with 'build -t', TAG instruction in the Dockerfile also should be taken effect.
ping @jfrazelle .

@cyphar
Copy link
Contributor

cyphar commented May 5, 2015

@xuxinkun I don't agree with the overriding point. If you don't allow ignoring of TAG instructions, what's to stop a random Dockerfile from clobbering a tagged image and thus tricking you into running containers you don't mean to.

@xuxinkun
Copy link

xuxinkun commented May 5, 2015

@cyphar overriding will be checked in 'TAG' command. So the condition you say won't happen. That's why I don't agree to use 'build -t' to ignore the 'TAG' command.

I will show u a example with my pull request #12983

[root@localhost VFS]# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
test                v1                  98354e5ca627        25 seconds ago      0 B
[root@localhost VFS]# cat Dockerfile 
FROM scratch
USER root
TAG test:v1
[root@localhost VFS]# docker build .
Sending build context to Docker daemon 2.048 kB
Sending build context to Docker daemon 
Step 0 : FROM scratch
 ---> 
Step 1 : USER root
 ---> Running in e7da47ddcdf7
 ---> 33c38b267b5e
Removing intermediate container e7da47ddcdf7
Step 2 : TAG test:v1
INFO[0000] Conflict: Tag v1 is already set to image 98354e5ca62793a497ee69fc06f8e3dfcae8d084db6be6e44a4d57927fe56233, if you want to replace it, please use -f option 

As you see, overriding will be stoped.

@cyphar
Copy link
Contributor

cyphar commented May 5, 2015

Yeah, but then people will just start using docker build -f each time because it's a pain to manually untag images.

@cpuguy83
Copy link
Member

cpuguy83 commented May 5, 2015

I'm definitely -1 on this concept.
Allowing the dockerfile itself to set how the image is to be referenced just isn't right, IMO.

@xuxinkun
Copy link

xuxinkun commented May 6, 2015

@cyphar Now I change my mind, I think TAG can override the others by default. Because docker build -t can override other tags also. As #5603 (comment) say, I will provide '-t' to ignore the 'TAG' instruction. How about your think?

@cyphar
Copy link
Contributor

cyphar commented May 6, 2015

I'm with @cpuguy83. My complaints were merely about "if this feature was a must have, there are certain security implications". I'm definitely -1 on this concept -- why would you allow developers to tell sysadmins what the image should be tagged as? There's a reason that tagging is separate to image ids -- so sysadmins can come up with naming schemes and developers can just define images.

@thaJeztah
Copy link
Member

I haven't really made my mind up on it; If I downloaded someone else's Dockerfile, this could be a bit weird. Otoh, when creating your own Dockerfile, this could be a really handy feature to (re)build all the images in one go.

Perhaps other tooling, e.g. a simple shell-script / Makefile is more suitable for that (it's what we're using now).

Does anyone know the history or expected usage pattern for multiple FROMs in a Dockerfile?

I really don't know. I guess we need to look when it was implemented. Could it be that it wasn't explicitly implemented, but just "worked" that way, and described as a "feature" in a later stage?

If we want to deprecate it, we probably have to do a GitHub search again to see if people are actually using it? (Like we did some time ago)

@ewindisch
Copy link
Contributor

@cyphar @duglin @thaJeztah As I see it, the only currently useful application of multiple FROMs is to execute pre-build scripts which modify network/cloud resources. That's a pretty narrow use-case, leaves untagged images on disk, and may have its own security implications. I propose we simply remove it.

@thaJeztah
Copy link
Member

@duglin can you open an issue for removing that feature (multiple FROM)?

Probably best to ping some "early contributors", just to double check there are no other reasons for it to be there than @ewindisch commented.

@duglin
Copy link
Contributor

duglin commented May 6, 2015

@thaJeztah done #13026

@danse
Copy link

danse commented May 8, 2015

👍 for this.

Other systems managing dependency between resources usually state what every element needs but also what it is going to provide. This it is convenient for troubleshooting, and for analysing a dependency tree out of a static collection of Docker files.

In order to make the correspondence between every Docker file and its tagged image more clear, in my company we will have to use naming conventions.

Arguments passed via the command line do not leave any track, while a declarative way to specify the name of the new image would help documenting and understanding the goal of every Docker file, in my opinion

@rantoniuk
Copy link

Reading the discussion I want to clarify something - #13774.
I am seeing a "TO" reference as a default behavior. This is not for the developers to decide on the tagging scheme. This is for them to easily build the images and tag them locally, as well as sysadmins actually.

The sysadmins need to tag them anyway right now via specyfing -t, but they need to use "magic scripting" to do that, what actually should be built into the tool.
If I would think on the same page I could say, why the developers are able to decide from which image they should descend FROM.

@rysiekpl
Copy link

rysiekpl commented Jun 6, 2015

I am also very interested in this feature.

@tiborvass
Copy link
Contributor

Collective review with @duglin @estesp @tianon @abronan @cpuguy83

The biggest problem with this proposal is that it would overwrite the user's image name. Example:
TAG ubuntu when I already have an ubuntu image. By the way this was already discussed here: #886 (comment)

It seems that the usecases described in this thread, can be resolved by either using a Compose file specifying the tags for each container, or by writing a simple Makefile.

However, if Dockerfiles evolve over time to be more powerful and flexible like a Makefile, with more security features such as ACLs on containers and images, thus eliminating the overwrite issue, then we could potentially revisit this.

I'm closing this issue for now, feel free to comment further if needed.

@rysiekpl
Copy link

@tiborvass hmmm

It seems that the usecases described in this thread, can be resolved by either using a Compose file specifying the tags for each container

Can't find a way to do this, am I missing something, or is this so far just a proposed feature of docker compose?

@richard-fairthorne
Copy link

Here's a workaround for unix like OS's, or sh users.

#!hb-path docker -t somecompany/sometag
FROM ubuntu:16.04
[...]

It uses my hb-path wrapper script. Make Dockerfiles executable. If you wish to use a different tag, just run Docker the normal way.

https://github.com/richard-fairthorne/hb-helpers

@DarrenBishop
Copy link

DarrenBishop commented Jun 1, 2018

I feel we may be over thinking the purpose of tags.

Surely like in the SCM-sense they are just light-weight pointers to commits and do not have any inherent meaning; semantics are subsequently applied when a tool is later used and must decide (validate) the tag is fit for its own interests.

@cyphar I do not agree that tagging is solely within the remit of SysAdmins, nor is conjuring naming conventions; where these responsibilities lie is fluid, changing from one team/project/(sub-)organisation to the next.

Not only are tags light-weight, but they are also only local to the Docker daemon, as is the image/commit itself, until a tool publishes them i.e. docker push ... and applies meaning.

So a developer/devops/sysadmin/Jenkins can do whatever they want up to that point.

@tiborvass regarding the issue of overwriting ubuntu, how different is:

docker build -t ubuntu .

I will (naively) offer there are no security issues either, not until you try to use some security-aware tool that must at that point do its own checks and validations (dude-diligence [any security-aware tool that does not, we should not be using]) to succeed.

What makes this really moot, is that we can all get the end result we want right now; imagine a multi-stage build:

# .../my-app/Dockerfile
FROM half-fat as build

ENV PROJECT_NAME my-app

...
RUN install some-fat-build-tool

RUN some-fat-build-tool build-all-the-things-to /just/the/healthy/stuff

ENTRYPOINT ["some-fat-build-tool"]

LABEL ${PROJECT_NAME}.image=builder

...
ADD http://download.some/test/dependency.ext.tgz /deps
COPY test/integration/mongodb test/integration/mongodb

RUN install some-test-tool and-other-fat-test-dependencies

ENTRYPOINT ["some-test-tool"]

LABEL ${PROJECT_NAME}.image=tester

FROM no-fat

ENV PROJECT_NAME my-app

COPY --from=build /just/the/healthy/stuff /app

...

ENTRYPOINT ["/app/bin/my-app"]

LABEL ${PROJECT_NAME}.image=application

You can then use those labels to find the commits/layers/intermediate-images and tag them as you please:

PROJECT_NAME=my-app

docker build -t ${PROJECT_NAME} .

BUILDER_HASH=$(docker images --filter label=${PROJECT_NAME}.image=builder -q -a | head -1)
echo "Tagging 'builder' layer for ${PROJECT_NAME} at ${BUILDER_HASH}"
docker tag ${BUILDER_HASH} ${PROJECT_NAME}:builder

TESTER_HASH=$(docker images --filter label=${PROJECT_NAME}.image=tester -q -a | head -1)
echo "Tagging 'tester' layer for ${PROJECT_NAME} at ${TESTER_HASH}"
docker tag ${TESTER_HASH} ${PROJECT_NAME}:tester

Note: the above example can be further parameterised e.g. with a version number, --build-arg VERSION=$VERSION and the ARG instruction.

Then you can use these images to do some really useful stuff:

docker run -d --name ${PROJECT_NAME}-database mongdb

docker run -it --rm --link ${PROJECT_NAME}-database -v ${PWD}/test/integration/data:/var/lib/test-data ${PROJECT_NAME}:tester --setup-test-data

docker run -it --rm --link ${PROJECT_NAME}-database ${PROJECT_NAME} --do=some-action --on=some-document-id

docker run -it --rm --link ${PROJECT_NAME}-database ${PROJECT_NAME}:tester --check-test-results

So with all of that insight (use-case and use of available features), why not just support the TAG instruction and make it easy?

@smaslennikov
Copy link

Old thread, but still a useful feature that doesn't exist.

@CannibalKush
Copy link

The use case for this for me is that I have to do my bash scripting in my build agent to properly tag my images in a CI / CD pipeline.

@cpuguy83
Copy link
Member

If you really want this functionality, take a look at implementing your own buildkit frontend. There is a dockerfile parser frontend that you can just add this keyword yourself.

This sounds scary, but it works very well. You can build it with "docker build" as normal (provided you are on 18.06 or newer).

Here is the docs for the official docker experimental frontend: https://github.com/moby/buildkit/blob/master/frontend/dockerfile/docs/experimental.md

You can take the Dockerfile frontend found in that repo and add the functionality you want, make an image, and reference that image at the top of your Dockerfile which tells docker how to parse the Dockerfile with "# syntax="

@blop
Copy link

blop commented May 13, 2019

The issue is that the TAG usually combines both the image name and version.

The docker build --tag , -t expects a name:tag value (which itself is weird, documentation should states name:version or something else and avoid reusing the same 'tag' keyword).
https://docs.docker.com/engine/reference/commandline/build/

In the opposite, the Docker Hub presentation shows tags as only the second part, which is more like a version/flavor of the image. See https://hub.docker.com/_/docker?tab=tags for example.

Most people arguing in favor of defining the image tag(s) from within the Dockerfile are doing so in order to simplify automated builds. As automating builds is a good thing, this should be encouraged.

This would also allows people to make dynamic computation of complex version easier, without the need for additionnal scripts/tools.

Maybe defining only the version(s) from within the Dockerfile and keep the image base name definition as a parameter of the docker build command would satisfy everyone?

@cpuguy83
Copy link
Member

are doing so in order to simplify automated builds

How does this simplify automated builds?

btw, I encourage you to take a look at the new docker buildx bake command (in 19.03 beta... buildx can also be run stand-alone).
Here is an example of that: https://gist.github.com/cpuguy83/32532552620f4dde7a03739c9a37b020

@ssrobins
Copy link

ssrobins commented Nov 6, 2019

Here's my use case for TAG:

I build custom docker images in GitLab CI which I use as the build environment for C++ applications. I'd like my tag to label which version of gcc my image has so my application builds with a specific version. I'd like the tag to be in one place so it's impossible for the gcc image version and the tag to be inconsistent. If I can set TAG inside the Dockerfile, this is easy:

ARG gcc_version=9.2.0
FROM gcc:$gcc_version
TAG docker-cpp-linux:gcc$gcc_version

Whether I'm running docker build . on my dev machine or in the CI, my tag is always correct.

I read a little about buildx and it might work, but not until it's on by default because GitLab's docker setup is outside of my control. I'd still prefer everything to be in the Dockerfile. Its purpose is to define my image, and the tag is a vital part of my image.

Today, I'm stuck either duplicating information between the docker build -t command and the FROM command inside the Dockerfile or wrap the docker build command in a shell script where I pass in a variable I can use in the Dockerfile. The downside with the shell script is docker build . will no longer work, which will be confusing to other users.

@dm17
Copy link

dm17 commented Nov 20, 2019

Can docker pull tags from .env like docker-compose? Seems not. Ideally, I'd like to be able to do FROM image:version AS imgname:$TAG - where I get $TAG from .env (like I do for docker-compose)... Possible?
Thanks.

@thaJeztah
Copy link
Member

thaJeztah commented Dec 3, 2019

Can docker pull tags from .env like docker-compose? Seems not. Ideally, I'd like to be able to do FROM image:version AS imgname:$TAG - where I get $TAG from .env (like I do for docker-compose)... Possible?

Using build-args in the AS ... is not possible, but if you want to specify the image to pull, that's possible;

ARG FOO_VERSION=1.2.3

FROM image:$FOO_VERSION AS base


FROM base AS some-stage

FROM base AS some-other-stage

Also note that the AS xxx only creates a reference known during the build, but won't tag a local image with that name (i.e., doing FROM foo:latest AS bar:1.2.3 won't create a local image named bar:1.2.3 in docker images)

@cyphar
Copy link
Contributor

cyphar commented Dec 20, 2019

I should probably mention that adding this today would probably be a fairly "fun" attack vector for clouds which allow you to build your own images (if you add TAG ubuntu:18.04 on an image you build, you can now get everyone else to run your malicious binaries!).

@marcellodesales
Copy link

I just want to compute the tag from within the docker image itself and set the value...

  • Generate multiple env vars based on the image
  • Store them as envs to the built image
  • Tag the image specifically from within
    • Why? Because we don't depend on any external entity
RUN echo "TAG_NAME=my-image-tag-base-on-env" >> /tag-values
RUN echo "TAG_NAME_DATE=$(date)" >> /tag-values
ENV --from-context-files /tag-values
TAG myimage:${TAG_NAME}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area/builder kind/feature Functionality or other elements that the project doesn't currently have. Features are new and shiny
Projects
None yet
Development

Successfully merging a pull request may close this issue.