Difference between COPY and ADD in Dockerfile
- COPY and ADD are both DockerFile instructions that serve a similar purpose
- Both COPY and ADD let you copy files from a specific location into a Docker image.
ADD
- The
ADD
instruction copies new files, directories or remote file URLs from<src>
and adds them to the filesystem of the image at the path<dest>
. - ADD also allow you to extract a tar file from the source directly into the destination.
Let’s take a simple example by using this Dockerfile
FROM busybox
ADD test.txt /tmp
CMD ["sh"]
At the same time create a file, as in step2 of Dockerfile we are trying to copy the file to /tmp directory
$ touch test.txt
- Now try to build this image
$ docker build -t mytestbusybox .
Sending build context to Docker daemon 3.072kB
Step 1/3 : FROM busybox
---> 19485c79a9bb
Step 2/3 : ADD test.txt /tmp
---> bf7ed7f1f246
Step 3/3 : CMD ["sh"]
---> Running in 83571f77d490
Removing intermediate container 83571f77d490
---> bc96c56b313a
Successfully built bc96c56b313a
Successfully tagged mytestbusybox:latest
- To verify it
$ docker image ls
REPOSITORY TAG IMAGE ID CREATED SIZE
mytestbusybox latest bc96c56b313a 3 minutes ago 1.22MB
- Start and login to the container using this image
$ $ docker run -it mytestbusybox sh
/ #
- Similar to above, we can add url
- Also, you can add tar file
- Let’s create a tar file
$ tar -cvf mytesttar test.txt Dockerfile
test.txt
Dockerfile
$ ls -ltr
-rw-rw-r--. 1 cloud_user cloud_user 10240 Sep 26 23:48 mytesttar
$ file mytesttar
mytesttar: POSIX tar archive (GNU)
- Here is the Dockerfile will look like
- Build it
- Run the container
$ docker run -dit mytesttar sh
64d4a2f42ecf40c3db52e148a9761289713327052d3545a891324162da88e273
- Try to login into the container, you will see the tar files are already extracted
$ docker exec -it 64d4a2f42ecf sh
/ # cd /tmp
/tmp # ls -ltr
total 4
-rw-rw-r-- 1 1002 1003 0 Sep 26 23:29 test.txt
-rw-rw-r-- 1 1002 1003 117 Sep 26 23:36 Dockerfile
NOTE: ADD
to fetch packages from remote URLs is strongly discouraged; you should use curl
or wget
instead. That way you can delete the files you no longer need after they’ve been extracted and you don’t have to add another layer in your image.
COPY
- The
COPY
instruction copies new files or directories from<src>
and adds them to the filesystem of the container at the path<dest>
.
HEALTHCHECK HEALTHCHECK
instruction tells Docker how to test a container to check that it is still working.
- When Docker starts a container, it monitors the process that the container runs. If the process ends, the container exits.
- This is just a basic check and doesn’t necessarily tell the details about the application.
To test this, let run one test container
$ docker container run -dt --name mybusybox busybox sh
8a47bdd73c02b31dc874a761e85f2922d1b67a923348bc660038bd7af7c9c5cb
- This time let’s try an elegant way to get the IP of this container, we can do it with the combination of inspect and format
$ docker inspect --format '{{ .NetworkSettings.IPAddress }}' mybusybox
172.17.0.2
- Let’ create a Dockerfile with healthcheck instructions
FROM busybox
HEALTHCHECK --interval=5s CMD ping -c 1 172.17.0.2
The options that can appear before CMD
are:
--interval=DURATION
(default:30s
)--timeout=DURATION
(default:30s
)--start-period=DURATION
(default:0s
)--retries=N
(default:3
)- Let’s build this image
$ docker build -t healthcheck_image .
Sending build context to Docker daemon 2.048kB
Step 1/2 : FROM busybox
---> 19485c79a9bb
Step 2/2 : HEALTHCHECK --interval=5s CMD ping -c 1 172.17.0.2
---> Running in 1b828fa681d6
Removing intermediate container 1b828fa681d6
---> ca8599a83d24
Successfully built ca8599a83d24
Successfully tagged healthcheck_image:latest
- Run our container using this image
$ docker container run -dt --name healthcheck_monitor healthcheck_image
303b02dfe6d0b0839766eb7ff7419ddd08283f842af0d8c62fd5043bf0df590b
- This time pay special attention to the STATUS column
$ docker container ls
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
303b02dfe6d0 healthcheck_image "sh" 34 seconds ago Up 32 seconds (healthy) healthcheck_monitor
8a47bdd73c02 busybox "sh" 7 minutes ago Up 7 minutes mybusybox
- If you run inspect on that container, you will see something like this
$ docker container inspect 303b02dfe6d0
"State": {
"Status": "running",
"Running": true,
"Paused": false,
"Restarting": false,
"OOMKilled": false,
"Dead": false,
"Pid": 4551,
"ExitCode": 0,
"Error": "",
"StartedAt": "2019-10-08T22:57:40.771481841Z",
"FinishedAt": "0001-01-01T00:00:00Z",
"Health": {
"Status": "healthy",
"FailingStreak": 0,
"Log": [
{
"Start": "2019-10-08T22:58:44.261195228Z",
"End": "2019-10-08T22:58:44.470254485Z",
"ExitCode": 0,
"Output": "PING 172.17.0.2 (172.17.0.2): 56 data bytes\n64 bytes from 172.17.0.2: seq=0 ttl=64 time=0.103 ms\n\n--- 172.17.0.2 ping statistics ---\n1 packets transmitted, 1 packets received, 0% packet loss\nround-trip min/avg/max = 0.103/0.103/0.103 ms\n"
},
{
"Start": "2019-10-08T22:58:49.484598427Z",
"End": "2019-10-08T22:58:49.652449457Z",
"ExitCode": 0,
"Output": "PING 172.17.0.2 (172.17.0.2): 56 data bytes\n64 bytes from 172.17.0.2: seq=0 ttl=64 time=0.096 ms\n\n--- 172.17.0.2 ping statistics ---\n1 packets transmitted, 1 packets received, 0% packet loss\nround-trip min/avg/max = 0.096/0.096/0.096 ms\n"
},
{
"Start": "2019-10-08T22:58:54.661236027Z",
"End": "2019-10-08T22:58:54.857234836Z",
"ExitCode": 0,
"Output": "PING 172.17.0.2 (172.17.0.2): 56 data bytes\n64 bytes from 172.17.0.2: seq=0 ttl=64 time=0.101 ms\n\n--- 172.17.0.2 ping statistics ---\n1 packets transmitted, 1 packets received, 0% packet loss\nround-trip min/avg/max = 0.101/0.101/0.101 ms\n"
},
{
"Start": "2019-10-08T22:58:59.862231367Z",
"End": "2019-10-08T22:59:00.059626755Z",
"ExitCode": 0,
"Output": "PING 172.17.0.2 (172.17.0.2): 56 data bytes\n64 bytes from 172.17.0.2: seq=0 ttl=64 time=0.101 ms\n\n--- 172.17.0.2 ping statistics ---\n1 packets transmitted, 1 packets received, 0% packet loss\nround-trip min/avg/max = 0.101/0.101/0.101 ms\n"
},
{
"Start": "2019-10-08T22:59:05.067737964Z",
"End": "2019-10-08T22:59:05.250376204Z",
"ExitCode": 0,
"Output": "PING 172.17.0.2 (172.17.0.2): 56 data bytes\n64 bytes from 172.17.0.2: seq=0 ttl=64 time=0.090 ms\n\n--- 172.17.0.2 ping statistics ---\n1 packets transmitted, 1 packets received, 0% packet loss\nround-trip min/avg/max = 0.090/0.090/0.090 ms\n"
}
]
}
},
- Now let’s do some experiment and shutdown, which is been monitored by HEALTHCHECK instruction
$ docker container stop 8a47bdd73c02
8a47bdd73c0
- Check the status again, this time you will see STATUS as unhealthy.
$ docker container ls
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
303b02dfe6d0 healthcheck_image "sh" 4 minutes ago Up 4 minutes (unhealthy) healthcheck_monitor
ENTRYPOINT: An ENTRYPOINT
allows you to configure a container that will run as an executable.
TICK TICK Interview Question? What is the main difference between ENTRYPOINT and CMD?
ENTRYPOINT doesn’t allow you to override the command.
- This is how my dockerfile look like with entrypoint instruction
FROM busybox
ENTRYPOINT ["/bin/ping"]
- Let’s build this image
$ docker build -t entrypoint .
Sending build context to Docker daemon 2.048kB
Step 1/2 : FROM busybox
---> 19485c79a9bb
Step 2/2 : ENTRYPOINT ["/bin/ping"]
---> Using cache
---> 6cb5dc1118a0
Successfully built 6cb5dc1118a0
Successfully tagged entrypoint:latest
- Now if you try to build the container out of this image
$ docker container run -dt --name entrypoint01 entrypoint sh
8e6cb454084f1156652f8541c14c6fe5d2cac3a09cd46ba8c82e1cb188919fa3
- Verify it, you will see something interesting, the ping command is trying to ping the sh
$ docker container ls -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
8e6cb454084f entrypoint "/bin/ping sh" 17 seconds ago Exited (1) 14 seconds ago entrypoint01
- If you run this command (-c 10 www.google.com), you will see the proper output
$ docker container run -dt --name entrypoint02 entrypoint -c 10 www.google.com
e0906011f6b90d45a14f70491ad4b7fc31af8b86129171eaca0be1bb2a1de8df
- To verify it
$ docker container ls
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
e0906011f6b9 entrypoint "/bin/ping -c 10 www…" 5 seconds ago Up 3 seconds entrypoint02
- Let’s try to do it with CMD
$ cat Dockerfile
FROM busybox
CMD ["sh"]
- Build the image
$ docker build -t cmdimage .
Sending build context to Docker daemon 2.048kB
Step 1/2 : FROM busybox
---> 19485c79a9bb
Step 2/2 : CMD ["sh"]
---> Running in 926a64c36950
Removing intermediate container 926a64c36950
---> 9888f3568e1f
Successfully built 9888f3568e1f
Successfully tagged cmdimage:latest
- Run the container, using this image
$ docker run -dt --name cmdcontainer01 cmdimage sh
b275a5b3b7b1b28ce261de1660c1e401af8f278e8d541575bb1d7bfa32ef3a64
- Verify it
$ docker container ls
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
b275a5b3b7b1 cmdimage "sh" 9 seconds ago Up 7 seconds cmdcontainer01
- Now rather than giving the default command(sh), let’s give ping command
$ docker run -dt --name cmdcontainer02 cmdimage ping -c 3 www.google.com
225c59e9e631085e33eb863d686e2bac4eae393ffe46eaa82eb9ab3b5a0de064
- Verify it
$ docker container ls
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
225c59e9e631 cmdimage "ping -c 3 www.googl…" 4 seconds ago Up 3 seconds cmdcontainer02
- So the point I am trying to Drive here, in case of CMD instruction it’s possible to override the default command but it’s not possible in case of ENTRYPOINT instruction.
- One more thing you can do is to use ENTRYPOINT and CMD in conjunction
FROM ubuntu
ENTRYPOINT ["sleep"]
CMD ["5"]
- Where you can ENTRYPOINT as a default command
- CMD as an instruction you can change.
This is a good place, to stop for Day 5
Please follow me with my Journey
- Website:https://100daysofdevops.com/
- Twitter:@100daysofdevops OR @lakhera2015
- Facebook:https://www.facebook.com/groups/795382630808645/
- Medium:https://medium.com/@devopslearning
- GitHub:https://github.com/100daysofdevops/21_Days_of_Docker
This time to make learning more interactive, I am adding
- Slack
- Meetup
Please feel free to join this group.
Slack:
Meetup Group
If you are in the bay area, please join this meetup group https://www.meetup.com/100daysofdevops/
Thanks a lot for sharing this with all grouping you truly realize what you’re conversation about! Bookmarked. Delight also cover with my website =). We could get a unite vary statement between us!