3. Building Docker Images: Dockerfile syntax

master
Jason Zhu 2020-11-29 16:20:04 +11:00
parent 61e1eff44b
commit 07bc28b276
5 changed files with 208 additions and 0 deletions

View File

@ -0,0 +1,196 @@
# 3. Building Docker Images
## What are Dockerfile?
**Dockerfile**:
* is a small "program" to create an image
* Run Dockerfile using `docker build -t name_of_container .`
* where `.` means Dockerfile is here
* `-t name_of_contain` mean tag the container
* When finished, the result will be in local docker registry, ready to be run
### Producing the Next Image with Each Step
* Each line (step) in Dockerfile takes the image from the previous line and make another image
* The previous images is unchanged
* state is not carried forward from line to line
* Multiple command in oneline is different from multiple commands in separate line
* Hence, you don't want large files to span lines, otherwise, the image is too large
* e.g. Download a large file, edit it, and delete it; If done in oneline, the image is small, otherwise, it's big
Details of working with Dockerfile are available in [Dockerfile reference](https://docs.docker.com/engine/reference/builder/)
### Caching with Each Step
* `docker build` using Dockerfile will save output of each step in cache
* Watch build output for "using cache"
* Docker will skips lines that have not changed since the last build. Time/resource saved
* Caching saves huge amounts of time
* Tip of editing Dockerfile: always put the parts that make change at the end of Dockerfile
### Dockerfile != Shell Scripts
* Dockerfiles look like shell scripts
* But they are not same
* Process in one line won't be running on next line
* Each line run for the duration of that container, then container gets shutdown, saved into an image. Fresh start on next line
* If two programs need passing values in same container, they have to be in same line
* Environment variables can be passed to next line using `ENV` cmd
Summary to notify: each line in Dockerfile is its own call to `docker run`
## Building Dockerfiles
### The Most Basic Dockerfile
Create a simple Dockerfile with following lines
```dockerfile
FROM busybox
RUN echo "building simple docker images."
CMD echo "Hello Container"
```
Build image using this Dockerfile `docker build -t hello .`, result in build output as shown below:
```
Sending build context to Docker daemon 2.048kB
Step 1/3 : FROM busybox
latest: Pulling from library/busybox
5f5dd3e95e9f: Pull complete
Digest: sha256:9f1c79411e054199210b4d489ae600a061595967adb643cd923f8515ad8123d2
Status: Downloaded newer image for busybox:latest
---> dc3bacd8b5ea
Step 2/3 : RUN echo "building simple docker image"
---> Running in 1990ae4f8398
building simple docker image
Removing intermediate container 1990ae4f8398
---> cf5a3650fa24
Step 3/3 : CMD echo "hello container"
---> Running in 3e3b64874c2c
Removing intermediate container 3e3b64874c2c
---> 4a0a8c1c2d1b
Successfully built 4a0a8c1c2d1b
Successfully tagged hello:latest
```
1. In step 1/3, a image `dc3bac...` is created.
2. In step 2/3, a container `1990ae...` is created using the image as shown; And `echo "building ..."` is executed using `RUN` command.
1. The container is also removed at the end of Step 2/3 as no body is using this container any more.
3. In step 3/3, a new container `3e3b...` is created, added command `echo` using `CMD`, which is then saved as new image `4a0a...`
Running the image `4a0a...` via: `docker run --rm hello`, will print "hello container"
### Installing a Program with Docker Build
Create a new Dockerfile:
```Dockerfile
FROM debian:sid
RUN apt-get -y update
RUN apt-get -y upgrade
RUN apt-get -y install nano
CMD "nano" "/tmp/notes"
```
### Adding a File through Docker Build
Start from previous built image
```Dockerfile
FROM example/nanoer
ADD notes.txt /notes.txt
CMD "nano" "/notes.txt"
```
In the same directory, create a notes.txt with inputted words. This dockerfile will add required file into image
## Dockerfile syntax
### The FROM statement
* Indicate which image to download and start from
* Must be the first cmd in Dockerfile
### The MAINTAINER Statement
* Defines the author of this Dockerfile
```Dockerfile
MAINTAINER Firstname Lastname <email@example.com>
```
### The RUN Statement
* Runs the command line, waits for it to finish, and saves the result
```Dockerfile
RUN unzip install.zip /opt/install/
```
### The ADD Statement
* Adds local files `ADD run.sh /run.sh`
* Adds the contents of tar archives
* `ADD project.tar.gz /install/`, it will un-compress tar.gz and add to container
* Works with URLs as well
* `ADD https://project.example.com/download/1.0/project.rpm /project/`
### The ENV Statement
* Sets environment variables
* Both during the build and when running the image
```Dockerfile
ENV DB_HOST=db.production.example.com
ENV DB_PORT=5432
```
### The ENTRYPOINT and CMD Statement
* **ENTRYPOINT** specifies the start of the command to run
* **CMD** specifies the whole command to run
* If container acts like a cmd-line program, you can use ENTRYPOINT
* If you are unsure, CMD is more used
### Shell Form vs. Exec FORM
* ENTRYPOINT & CMD can use both forms
* **Shell form** looks like normal shell script:
* `nano notes.txt`
* **Exec form** looks like:
* `["/bin/nano", "notes.txt"]`
### The EXPOSE Statement
* Maps a port into the container
* `EXPOSE 8080`, same as `-p 8080` in `docker run`
### VOLUME Statement
* Defines shared or ephemeral volumes
* `VOLUME ["/host/path/" "/container/path/"]` map host path to container
* `VOLUME ["/shared-data"` create a volumes can be inherited by later containers
Tips: Avoid defining shared folders in Dockerfile, as it makes Dockerfile only work with the current computer
### WORKDIR Statement
* Sets the directory the container starts in after `docker run`
```dockerfile
WORKDIR /install/
```
### The USER Statement
* Sets which user the container will run as
* Useful when have a shared network directory involved a fixed username/number
```dockerfile
USER arthur
USER 1000
```
### TODO: Read docker reference guid
## Multi-project Docker files

View File

@ -0,0 +1,5 @@
FROM debian:sid
RUN apt-get -y update
RUN apt-get -y upgrade
RUN apt-get -y install nano
CMD "nano" "/tmp/notes"

View File

@ -0,0 +1,3 @@
FROM busybox
RUN echo "building simple docker image"
CMD echo "hello container"

View File

@ -0,0 +1,3 @@
FROM example/nanoer
ADD notes.txt /notes.txt
CMD "nano" "/notes.txt"

View File

@ -0,0 +1 @@
TODO: learn more about dockerfiles