24

I am writing a Dockerfile to build an application. I know that you can copy files out of the container manually with

docker cp <containerId>:/file/path/within/container /host/path/target

(see Copying files from Docker container to host), but I would like to just run

docker build

and have it dump the build artifacts created by my Dockerfile somewhere on my host file system.

Is there a command I can use within the Dockerfile to copy out of the container and into the host? Like the opposite of COPY?

Shubham
  • 2,847
  • 4
  • 24
  • 37
JamesFaix
  • 8,050
  • 9
  • 37
  • 73
  • 1
    Out of curiosity, what is the use-case here? i.e. if you're creating a Docker image (as opposed to running a container), why do you need/want stuff to come **out** of it? – Oliver Charlesworth Apr 03 '18 at 20:23
  • I do not understand the distinction between an "image" and "container". I am trying to build PDFium which has a large complicated build process, in such a way that I can just give a script to a coworker and they can build it as well. Then we want to have an output library file from the build process that we can use. – JamesFaix Apr 03 '18 at 20:27
  • 1
    A container is a runtime instantiation of an image. Generally speaking, you build an image from a Dockerfile via `docker build`, and then create instances (containers) from that image via `docker run`. I don't know the details of your situation here, but I'd be tempted to model this as a 3-step process: (1) construct a dedicated Docker image for performing isolated builds, (2) instantiate a container from this image, (3) run the PDFium build inside this container (and then extract the build artifact via one mechanism or another). – Oliver Charlesworth Apr 03 '18 at 20:32
  • Gotcha. I was hoping to encapsulate the environment setup and build into one script. I think i am going a little outside of intended docker usage. – JamesFaix Apr 03 '18 at 20:49
  • What if you docker image and then dumb to host? i tired your mention question with docker dind but its only work when container up – Adiii Apr 04 '18 at 07:22
  • If you need the artifacts to build another Docker image, have a look at [multi stage builds](https://docs.docker.com/develop/develop-images/multistage-build/). Otherwise I agree with @OliverCharlesworth. I would add to his comment that I usually create a shell script or a makefile with these steps: 1. build the image, 2. start a container from that image 3. use docker cp to copy my artifacts from the container to the host. – takacsmark Apr 04 '18 at 07:36
  • how about sharing a volume between your container and the host! something like `docker run -d -v /path/in/host:/path/to/artifact/in/container ....` – hichamx Apr 04 '18 at 10:46
  • @hichamx I tried using a volume, but within a Dockerfile, there doesn't seem to be any command to copy out of the container into the host. `COPY` only copies into the container, and a plain Bash `RUN cp here there` command doesn't seem to know about Docker volumes. – JamesFaix Apr 04 '18 at 11:34
  • I believe no such kind of thing in dockerfile, because image build could be done in any place, in dockerhub or in you local, so docker could not determine where to copy the files to, this is not adaptable. So you had to run it, then there will be chance for docker to copy the things in container to host. – atline Apr 04 '18 at 12:40
  • There are lots of pdfium containers prebuilt on docker hub. You can just use one of those without having to build your own. Eg: https://hub.docker.com/r/documentcloud/pdfium-alpine – Software Engineer Feb 26 '19 at 20:14

3 Answers3

14

As per Docker docs, API version 1.40 added

Custom build outputs

Which is intended for what you want:

By default, a local container image is created from the build result. The --output (or -o) flag allows you to override this behavior, and a specify a custom exporter. For example, custom exporters allow you to export the build artifacts as files on the local filesystem instead of a Docker image, which can be useful for generating local binaries, code generation etc.

For example

$ docker build --output type=tar,dest=out.tar .

with multi-stage Dockerfile

FROM golang AS build-stage
RUN go get -u github.com/LK4D4/vndr

FROM scratch AS export-stage
COPY --from=build-stage /go/bin/vndr /

The --output option exports all files from the target stage. A common pattern for exporting only specific files is to do multi-stage builds and to copy the desired files to a new scratch stage with COPY --from.

Marakai
  • 1,163
  • 11
  • 26
  • 1
    This is the best answer by far! The example is succinct and to the point! I was a bit puzzled by the construct: FROM scratch As export-stage. Then after googling, I realized scratch is a docker reserved keyword to denote "Docker's reserved, minimal image" – HAltos Dec 17 '20 at 01:25
  • very important to note this ONLY works with `DOCKER_BUILDKIT=1` otherwise nothing is outputed, with no errors – notzippy Jan 19 '22 at 17:12
4

Adding to @Marakai excellent answer, one has to set the env variable DOCKER_BUILDKIT=1. So the command would be:

$ DOCKER_BUILDKIT=1  docker build --output type=tar,dest=out.tar .

Or one could split into two commands:

$ export DOCKER_BUILDKIT=1
$ docker build --output type=tar,dest=out.tar .  # to gen into a tar file

Or to save the files without forming a tar file:

$ mkdir out
$ docker build  --output out .

The files will be copied to the directory out.

HAltos
  • 701
  • 7
  • 6
-1

Maybe this command is what you are searching for

docker run -v ~/data:/var/logs <image>

-v ~/data:/var/logs creates a bind mount volume that links the /var/logs directory from the container to the ~/data vdirectory on your host machine. Docker uses : to split the host's path from the container path.

I recommend the article on How To Share Data between Docker Containers

Matthias Sommer
  • 1,070
  • 13
  • 28
  • This is not suitable for multi stage docker build as only the last part is saved as the image so when you do docker run anything in the intermediate stages will not be available. However if one does not need the files from intermediate stages then he can copy the file from the built image this way. – Yeasin Ar Rahman Apr 03 '19 at 10:13
  • @jamesfaix is asking with reference to `docker build` and not `docker run`. To utilize `docker run`, you would first need to have an image which has been built with `docker build` – Shammi Shailaj Jul 06 '20 at 04:39
  • @MatthiasSommer: to make it more explicit, -v flag is available to docker run but NOT docker build. – HAltos Dec 17 '20 at 01:08