Create docker container image
by Wenwei Weng
Docker is growing with amazing features, and it becomes a platform to deploy services even in embedded linux enviroment. The container image creation is an important part of process. Docker has done great job to manage the container image to make it to be in layer fashion, this is especially important for storage efficiency.
The following post shows what I did to create a scratch hello image and a minimal linux image based on alpine using Dockerfile.
Dockerfile is the way docker has defined to create docker container image. It is kind of like GNU Makefile to build binary application from C source code. It has a set of simple instructions. For details, check Dockerfile reference and best Dockerfile practice
(There is another way to create a tar file and use “docker import “ to create a container name. But here I only use Dockerfile to create.)
Inside Dockerfile, each line docker build will create a layer. Layer is marked with checksum,it is used for file systme overlay to avoid duplication of same content across containers. More details, check here.
hello image from scratch
Objective: create a minimum container image to show “Hello from Docker by WENWEI WENG”.
How: Docker has a minimal image “scratch”, which is empty. It can be used as a starting point for building containers. Using the “scratch” image as a base to tell the build process that I want the next command in the Dockerfile to be the first filesystem layer in my image. From there, I add a static linked executable “hello” binary.
hello.c file:
iot@sg-ucs-1:~/temp-docker/hello-world$ cat hello.c
#include <sys/syscall.h>
#ifndef DOCKER_IMAGE
#define DOCKER_IMAGE "hello-world"
#endif
#ifndef DOCKER_GREETING
#define DOCKER_GREETING "Hello from Docker by WENWEI WENG!"
#endif
const char message[] =
"\n"
DOCKER_GREETING "\n"
"This message shows that a simple hellow world built from scratch is working.\n"
"\n";
void _start() {
syscall(SYS_write, 1, message, sizeof(message) - 1);
syscall(SYS_exit, 0);
}
iot@sg-ucs-1:~/temp-docker/hello-world$
it is good to notice that to print hello, printf() is not used, instead use syscall(), because printf() requires libc, which it needs to be avoided in this case. it is needed to build and linked statically like below.
Build hello.c
gcc -o hello -static -nostartfiles hello.c
hello.c: In function _start:
hello.c:36:2: warning: implicit declaration of function syscall [-Wimplicit-function-declaration]
syscall(SYS_write, 1, message, sizeof(message) - 1);
^
iot@sg-ucs-1:~/temp-docker/hello-world$ file hello
hello: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), statically linked, BuildID[sha1]=03031e04b4ccc726db7a44f84460e2f95834a9c8, not stripped
iot@sg-ucs-1:~/temp-docker/hello-world$ ldd hello
not a dynamic executable
iot@sg-ucs-1:~/temp-docker/hello-world$
Dockerfile:
iot@sg-ucs-1:~/temp-docker/hello-world$ cat Dockerfile
FROM scratch
ADD hello /
CMD ["/hello"]
iot@sg-ucs-1:~/temp-docker/hello-world$
Build container image
iot@sg-ucs-1:~/temp-docker/hello-world$ sudo docker build -t hello .
Sending build context to Docker daemon 6.144 kB
Step 1 : FROM scratch
--->
Step 2 : ADD hello /
---> f246c1ebded0
Removing intermediate container b8f2e862b305
Step 3 : CMD /hello
---> Running in 2590c17b439c
---> c47cc50ca9c3
Removing intermediate container 2590c17b439c
Successfully built c47cc50ca9c3
iot@sg-ucs-1:~/temp-docker/hello-world$ sudo docker images
REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
hello latest c47cc50ca9c3 7 seconds ago 2.064 kB
<none> <none> 366a6281a9f6 3 minutes ago 2.752 kB
<none> <none> b2fa06955e3a 10 hours ago 123.1 MB
elasticsearch latest 9bd9659e5b46 3 days ago 351.3 MB
jetty latest 6544cee122fe 3 days ago 318.9 MB
nginx latest cb2a085838a2 4 days ago 181.8 MB
mongo latest a1112943ce27 4 days ago 402.2 MB
golang latest 0f5f664883a2 4 days ago 696.6 MB
debian latest 81d47ee3898e 5 days ago 123.1 MB
debian jessie 81d47ee3898e 5 days ago 123.1 MB
ubuntu xenial e37d367c3507 5 days ago 130 MB
ubuntu trusty a437f423d026 5 days ago 188 MB
ubuntu 12.04 8436209beb19 5 days ago 103.6 MB
fedora latest b083ce60cff6 2 weeks ago 230.3 MB
registry latest c78f4fd8bf90 6 weeks ago 33.2 MB
busybox latest 1911ea24d99d 7 weeks ago 1.11 MB
centos latest 2785d012ae3e 11 weeks ago 191.8 MB
iot@sg-ucs-1:~/temp-docker/hello-world$ sudo docker run --rm hello
Hello from Docker by WENWEI WENG!
This message shows that a simple hellow world built from scratch is working.
iot@sg-ucs-1:~/temp-docker/hello-world$
Build a minimal linux image with a file named “test-alpine-weng.txt”
Objective: a minimal linux image with a file named “test-alpine-weng.txt”
How: starting with “alpine” image as base, add file “test-alpine-weng.txt””.
create the file “test-alpine-weng.txt”
iot@sg-ucs-1:~/temp-docker/alpine-weng$ cat test-alpine-weng.txt
adding a new file into alpine base image by Wenwei Weng.
iot@sg-ucs-1:~/temp-docker/alpine-weng$
Dockerfile
iot@sg-ucs-1:~/temp-docker/alpine-weng$ cat Dockerfile
FROM alpine
ADD test-alpine-weng.txt /
CMD ["cat /test-alpine-weng.txt"]
iot@sg-ucs-1:~/temp-docker/alpine-weng$
Build container image and run
iot@sg-ucs-1:~/temp-docker/alpine-weng$ sudo docker build -t alpine-weng .
Sending build context to Docker daemon 3.072 kB
Step 1 : FROM scratch
--->
Step 2 : ADD test-alpine-weng.txt /
---> 481b37eca163
Removing intermediate container 76feaa4e8422
Step 3 : CMD cat /test-alpine-weng.txt
---> Running in ac76f3fc697a
---> 0a6ea5edd612
Removing intermediate container ac76f3fc697a
Successfully built 0a6ea5edd612
iot@sg-ucs-1:~/temp-docker/alpine-weng$ vi Dockerfile
iot@sg-ucs-1:~/temp-docker/alpine-weng$ sudo docker build -t alpine-weng .
Sending build context to Docker daemon 3.072 kB
Step 1 : FROM alpine
---> 031b4db7df57
Step 2 : ADD test-alpine-weng.txt /
---> 3a4198f8c17b
Removing intermediate container 0e51f073610c
Step 3 : CMD cat /test-alpine-weng.txt
---> Running in bd34e7f24c95
---> 5bb6c4a478c8
Removing intermediate container bd34e7f24c95
Successfully built 5bb6c4a478c8
iot@sg-ucs-1:~/temp-docker/alpine-weng$ sudo docker images
REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
alpine-weng latest 5bb6c4a478c8 17 seconds ago 3.988 MB
<none> <none> 0a6ea5edd612 41 seconds ago 58 B
hello latest c47cc50ca9c3 5 minutes ago 2.064 kB
<none> <none> 366a6281a9f6 8 minutes ago 2.752 kB
<none> <none> b2fa06955e3a 10 hours ago 123.1 MB
alpine latest 031b4db7df57 27 hours ago 3.987 MB
elasticsearch latest 9bd9659e5b46 3 days ago 351.3 MB
jetty latest 6544cee122fe 3 days ago 318.9 MB
nginx latest cb2a085838a2 4 days ago 181.8 MB
mongo latest a1112943ce27 4 days ago 402.2 MB
golang latest 0f5f664883a2 4 days ago 696.6 MB
debian jessie 81d47ee3898e 5 days ago 123.1 MB
debian latest 81d47ee3898e 5 days ago 123.1 MB
ubuntu xenial e37d367c3507 5 days ago 130 MB
ubuntu trusty a437f423d026 5 days ago 188 MB
ubuntu 12.04 8436209beb19 5 days ago 103.6 MB
fedora latest b083ce60cff6 2 weeks ago 230.3 MB
registry latest c78f4fd8bf90 6 weeks ago 33.2 MB
busybox latest 1911ea24d99d 7 weeks ago 1.11 MB
centos latest 2785d012ae3e 11 weeks ago 191.8 MB
iot@sg-ucs-1:~/temp-docker/alpine-weng$ sudo docker run --rm -it alpine-weng /bin/sh
/ # ls
bin lib root sys var
dev media run test-alpine-weng.txt
etc mnt sbin tmp
home proc srv usr
/ # cat test-alpine-weng.txt
adding a new file into alpine base image by Wenwei Weng.
/ # exit
iot@sg-ucs-1:~/temp-docker/alpine-weng$
Reference
For more details, check docker docs.
Subscribe via RSS