== Build an Image *PURPOSE*: This chapter explains how to create a Docker image. As explained in <>, Docker image is the *build component* of Docker and a read-only template of application operating system. === Dockerfile Docker build images by reading instructions from a _Dockerfile_. A _Dockerfile_ is a text document that contains all the commands a user could call on the command line to assemble an image. `docker build` command uses this file and executes all the commands in succession to create an image. `build` command is also passed a context that is used during image creation. This context can be a path on your local filesystem or a URL to a Git repository. _Dockerfile_ is usually called _Dockerfile_. The complete list of commands that can be specified in this file are explained at https://docs.docker.com/reference/builder/. The common commands are listed below: .Common commands for Dockerfile [width="100%", options="header", cols="1,4,4"] |================== | Command | Purpose | Example | FROM | First non-comment instruction in _Dockerfile_ | `FROM ubuntu` | COPY | Copies mulitple source files from the context to the file system of the container at the specified path | `COPY .bash_profile /home` | ENV | Sets the environment variable | `ENV HOSTNAME=test` | RUN | Executes a command | `RUN apt-get update` | CMD | Defaults for an executing container | `CMD ["/bin/echo", "hello world"]` | EXPOSE | Informs the network ports that the container will listen on | `EXPOSE 8093` |================== === Create your first Docker image . Create a new directory. . Create a new text file, name it _Dockerfile_, and use the following contents: + [source, text] ---- FROM ubuntu CMD ["/bin/echo", "hello world"] ---- + This image uses `ubuntu` as the base image. `CMD` command defines the command that needs to run. It provides a different entry point of `/bin/echo` and gives the argument "`hello world`". + . Build this image: + ```console > docker build -t helloworld . Sending build context to Docker daemon 2.048 kB Step 0 : FROM ubuntu Pulling repository docker.io/library/ubuntu a5a467fddcb8: Download complete 3fd0c2ae8ed2: Download complete 9e19ac89d27c: Download complete ac65c371c3a5: Download complete Status: Downloaded newer image for ubuntu:latest ---> a5a467fddcb8 Step 1 : CMD /bin/echo hello world ---> Running in 132bb0bf823f ---> e81a394f71e3 Removing intermediate container 132bb0bf823f Successfully built e81a394f71e3 ``` + `.` in this command is the context for `docker build`. + . List the images available: + ```console > docker images REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE helloworld latest 9c0e7b56cbee 13 minutes ago 187.9 MB ``` + . Run the container: + docker run helloworld + to see the output: + hello world + . Change the base image from `ubuntu` to `busybox` in `Dockerfile`. Build the image again: + docker build -t helloworld2 . + and view the images as: + ```console > docker images REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE helloworld latest e81a394f71e3 26 minutes ago 187.9 MB helloworld2 latest c458787fadcf 3 seconds ago 1.113 MB ubuntu latest a5a467fddcb8 2 days ago 187.9 MB busybox latest 3d5bcd78e074 4 days ago 1.113 MB ``` === WildFly Image . Create a new directory. . Create a new text file, name it _Dockerfile_, and use the following contents: + [source, text] ---- FROM jboss/wildfly ---- + . Build the image: + docker build -t mywildfly . + . Run the container: + docker run -it mywildfly === Java EE 7 Application Image . Create a new directory. . Create a new text file, name it _Dockerfile_, and use the following contents: + [source, text] ---- FROM jboss/wildfly <1> CMD ["/opt/jboss/wildfly/bin/standalone.sh", "-c", "standalone-full.xml", "-b", "0.0.0.0"] <2> RUN curl -L https://github.com/javaee-samples/javaee7-hol/raw/master/solution/movieplex7-1.0-SNAPSHOT.war -o /opt/jboss/wildfly/standalone/deployments/movieplex7-1.0-SNAPSHOT.war <3> ---- + Three things in this image: + <1> Uses "`jboss/wildfly`" as the base image <2> Starts WildFly application server in Full Platform mode <3> Copies the WAR file from from a URL to the deployment directory of WildFly + . Build the image: docker build -t movieplex . === Dockerfile Command Design Patterns ==== Difference between CMD and ENTRYPOINT *TL;DR* `CMD` will work for most of the cases. Default entry point for a container is `/bin/sh`, the default shell. Running a container as `docker run -it ubuntu` uses that command and starts the default shell. The output is shown as: ```console > docker run -it ubuntu root@88976ddee107:/# ``` `ENTRYPOINT` allows to override the entry point to some other command, and even customize it. For example, a container can be started as: ```console > docker run -it --entrypoint=/bin/cat ubuntu /etc/passwd root:x:0:0:root:/root:/bin/bash daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin bin:x:2:2:bin:/bin:/usr/sbin/nologin sys:x:3:3:sys:/dev:/usr/sbin/nologin . . . ``` This command overrides the entry point to the container to `/bin/cat`. The argument(s) passed to the CLI are used by the entry point. ==== Difference between ADD and COPY *TL;DR* `COPY` will work for most of the cases. `ADD` has all capabilities of `COPY` and has the following additional features: . Allows tar file auto-extraction in the image, for example, `ADD app.tar.gz /opt/var/myapp`. . Allows files to be downloaded from a remote URL. However, the downloaded files will become part of the image. This causes the image size to bloat. So its recommended to use `curl` or `wget` to download the archive explicitly, extract, and remove the archive. ==== Import and export images Docker images can be saved using `save` command to a .tar file: docker save helloworld > helloworld.tar These tar files can then be imported using `load` command: docker load -i helloworld.tar