Working with Dockerfile
- Dockerfile is a text file that contains instructions on how to create docker images.
- These commands are known as directives
# This is comment
DIRECTIVE argument
Common Directives:
- FROM:
- This is used to set the base image/parent image
- This can be any image from Docker hub
FROM <image>:<tag>
if the tag is not mentioned latest tag will be applied/assumed by Docker image- If you want to build the docker image from scratch then use
FROM scratch
- LABEL”
- This is key-value pair used to add metadata to Docker Image
LABEL <KEY>=<VALUE>
- We can add multiple LABEL directives or multiple labels with space sepearted.
- RUN:
- This directive is used to execute the command during image build time.
- This will generally have application configuration/installation etc
- Any RUN command which impacts the storage a new layer will be created.
- CMD:
- This directive will be executed when the container is created when no ENTRYPOINT directive exists
- If the CMD is not present in current image it will execute parents CMD directive
- Container will be in running state as long as the instructions in CMD are executing
- The CMD has two forms exec and shell form
- EXEC form
CMD ["executable", "param1", ... , "paramn"]
CMD ["echo", "hello-world" ] - SHELL FORM
CMD executable param1 .. paramn
CMD echo hello-world
- EXPOSE:
- This directive will expose the port of the container
- ADD:
- This directive is used to copy files into docker image while building the image
- Syntax
ADD <src> <dest>
- For the ADD src can be local files as well as URL’s
- COPY:
- This directive is used to copy files into docker image while building the image
- Syntax
COPY <src> <dest>
- For COPY directive the source can be only local files
Lets start inspecting images
- Lets build a Docker image called as hello:0.1.0 Refer Here for the changeset
- If we use scratch copying the files with kernel and executables is also our responsibility so for this session since we focus on building containers for software applications, choose the base image with necessary files is good choice.
- Since we have built the image lets inspect it
docker image inspect hello:0.1.0
* Now lets take a docker image as parent which has some files in it Refer Here for the changes and lets build a new image hello:0.1.1
* lets inspect alpine image docker image inspect alpine:3.0
[
{
"Id": "sha256:e66264b98777e12192600bf9b4d663655c98a090072e1bab49e233d7531d1294",
"RepoTags": [
"alpine:3"
],
"RepoDigests": [
"alpine@sha256:686d8c9dfa6f3ccfc8230bc3178d23f84eeaf7e457f36f271ab1acc53015037c"
],
"Parent": "",
"Comment": "",
"Created": "2022-05-23T19:19:31.970967174Z",
"Container": "49320ab4701345c613d266d2b3cf2ff0265c553d463f9061e479b6c8ef839a1f",
"ContainerConfig": {
"Hostname": "49320ab47013",
"Domainname": "",
"User": "",
"AttachStdin": false,
"AttachStdout": false,
"AttachStderr": false,
"Tty": false,
"OpenStdin": false,
"StdinOnce": false,
"Env": [
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
],
"Cmd": [
"/bin/sh",
"-c",
"#(nop) ",
"CMD [\"/bin/sh\"]"
],
"Image": "sha256:f9ee3a3800e8eec1d8d7fb76906dd5859498b12d27a0258b3df35bca9fa8a867",
"Volumes": null,
"WorkingDir": "",
"Entrypoint": null,
"OnBuild": null,
"Labels": {}
},
"DockerVersion": "20.10.12",
"Author": "",
"Config": {
"Hostname": "",
"Domainname": "",
"User": "",
"AttachStdin": false,
"AttachStdout": false,
"AttachStderr": false,
"Tty": false,
"OpenStdin": false,
"StdinOnce": false,
"Env": [
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
],
"Cmd": [
"/bin/sh"
],
"Image": "sha256:f9ee3a3800e8eec1d8d7fb76906dd5859498b12d27a0258b3df35bca9fa8a867",
"Volumes": null,
"WorkingDir": "",
"Entrypoint": null,
"OnBuild": null,
"Labels": null
},
"Architecture": "amd64",
"Os": "linux",
"Size": 5524281,
"VirtualSize": 5524281,
"GraphDriver": {
"Data": {
"MergedDir": "/var/lib/docker/overlay2/dacb8a310bbe17ca0e4e83768b8c4d6ba6fe61d70916c59c49edf3242bc397c3/merged",
"UpperDir": "/var/lib/docker/overlay2/dacb8a310bbe17ca0e4e83768b8c4d6ba6fe61d70916c59c49edf3242bc397c3/diff",
"WorkDir": "/var/lib/docker/overlay2/dacb8a310bbe17ca0e4e83768b8c4d6ba6fe61d70916c59c49edf3242bc397c3/work"
},
"Name": "overlay2"
},
"RootFS": {
"Type": "layers",
"Layers": [
"sha256:24302eb7d9085da80f016e7e4ae55417e412fb7e0a8021e95e3b60c67cde557d"
]
},
"Metadata": {
"LastTagTime": "0001-01-01T00:00:00Z"
}
}
]
- Refer Here for changeset containing RUN directive and impact on docker image layers. Build a new image
hello:0.1.2
- Now lets inspect hello:0.1.2 specifically layers
- Docker image is collection of image layers
- For docker container to work these layers should be combine to form a file system
- Since docker images have layers and container need to process them docker has different storage drivers which help containers work with image layers.
- The container which we built is not running
- Lets assume We want to run the container for some time (1d) Refer Here for the changes
- Ideally the CMD should have some command or script which is executed as long as our application is running.
Scenario: Lets build a lamp server based on centos base image
- Refer Here for the steps, skip the mysql installation part
- Dockerfile
FROM centos:7
LABEL purpose="classroom" author="khaja"
RUN yum install httpd -y && yum install php php-mysql -y && systemctl enable httpd.service
EXPOSE 80
CMD ["sleep", "1d"]
-
This is not a good httpd but lets improve it Refer Here for the changes
-
Using Expose Instruction is mandatory for dynamic port forwarding
- Refer Here for all the changes done in the Dockerfile
Exercise
- Try creating Dockerfile for spring petclinic Refer Here
- Try creating Dockerfile for gameoflife Refer Here
Important Commands
- Listing Containers
-
Remove all the contianers