3. Building Docker Images: Dockerfile syntax
This commit is contained in:
parent
61e1eff44b
commit
07bc28b276
196
notes/3_building_docker_images.md
Normal file
196
notes/3_building_docker_images.md
Normal 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
|
||||
|
@ -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"
|
@ -0,0 +1,3 @@
|
||||
FROM busybox
|
||||
RUN echo "building simple docker image"
|
||||
CMD echo "hello container"
|
@ -0,0 +1,3 @@
|
||||
FROM example/nanoer
|
||||
ADD notes.txt /notes.txt
|
||||
CMD "nano" "/notes.txt"
|
@ -0,0 +1 @@
|
||||
TODO: learn more about dockerfiles
|
Loading…
x
Reference in New Issue
Block a user