Copying files during the build

Objectives

So far, we have installed things in our container images by downloading packages.

We can also copy files from the build context to the container that we are building.

Remember: the build context is the directory containing the Dockerfile.

In this chapter, we will learn a new Dockerfile keyword: COPY.

Build some C code

We want to build a container that compiles a basic “Hello world” program in C.

Here is the program, hello.c:

int main () {
  puts("Hello, world!");
  return 0;
}

Let’s create a new directory, and put this file in there.

Then we will write the Dockerfile.

The Dockerfile

On Debian and Ubuntu, the package build-essential will get us a compiler.

When installing it, don’t forget to specify the -y flag, otherwise the build will fail (since the build cannot be interactive).

Then we will use COPY to place the source file into the container.

FROM ubuntu
RUN apt-get update
RUN apt-get install -y build-essential
COPY hello.c /
RUN make hello
CMD /hello

Create this Dockerfile.

Testing our C program

  • Create hello.c and Dockerfile in the same directory.

  • Run docker build -t hello . in this directory.

  • Run docker run hello, you should see Hello, world!.

# docker run hello
Hello, world!

COPY and the build cache

  • Run the build again.

  • Now, modify hello.c and run the build again.

  • Docker can cache steps involving COPY.

  • Those steps will not be executed again if the files haven’t been changed.

[root@intranet-dev myc]# docker build -t hello .
Sending build context to Docker daemon  3.072kB
Step 1/6 : FROM ubuntu
 ---> 452a96d81c30
Step 2/6 : RUN apt-get update
 ---> Using cache
 ---> 01e04143b340
Step 3/6 : RUN apt-get install -y build-essential
 ---> Using cache
 ---> 9139dae8927e
Step 4/6 : COPY hello.c /
 ---> c803db9440ed
Step 5/6 : RUN make hello
 ---> Running in 3f92e8e74085
cc     hello.c   -o hello
hello.c: In function 'main':
hello.c:2:3: warning: implicit declaration of function 'puts' [-Wimplicit-function-declaration]
   puts("Hello, big world!");
   ^~~~
Removing intermediate container 3f92e8e74085
 ---> 2d25a58a49f0
Step 6/6 : CMD /hello
 ---> Running in be79b29a07e0
Removing intermediate container be79b29a07e0
 ---> aae25a3dfa28
Successfully built aae25a3dfa28
Successfully tagged hello:latest

Details

  • You can COPY whole directories recursively.

  • Older Dockerfiles also have the ADD instruction. It is similar but can automatically extract archives.

  • If we really wanted to compile C code in a container, we would:

    • Place it in a different directory, with the WORKDIR instruction.

    • Even better, use the gcc official image.