Create docker container image

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.

docker install

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.