This article will describe usage of Docker.
Table of Contents
1 Install docker-engine
2 Image and container
Image is an immutable root filesystem created from Dockerfile. Image is not used at runtime.
Container is a mutable root filesystem created from image. Container is used at runtime.
For example, the following command will result in as below.
$ docker run hello-world <snip> Hello from Docker! <snip>
- Download hello-world image from remote server.
- Container with a random name is created from image.
- A binary hello specified by CMD in Dockerfile outputs "Hello from Docker!".
Running binary hello on host machine outputs the same. But this is not the same environment.
$ sudo /var/lib/docker/aufs/diff/<hash>/hello <snip> Hello from Docker! <snip>
3 Download image and run command on container
There are two way. One is running "docker run". Another is "docker pull", "docker create" and "docker start".
3.1 docker run
Running the following "docker run" will download <image> and run <cmd> on <container>.
$ docker run -it --name <container> <image> <cmd>
- Omitting –name <container> creates random name.
- Omitting <cmd> uses CMD in Dockerfile.
- You can use ID to <container> and <images>.
This "docker run" is same with the following commands. If omitting "docker pull" and <image> is not exist, "docker create" will download <image> from remote server.
$ docker pull <image> $ docker create -it --name <container> <image> <cmd> $ docker start -i <container>
3.2 docker pull
"docker pull" is a command for downloading image to local. Image is downloaded from remote server called Registry. The default registry is Docker Hub.
Because "docker create" search will image from local first, you can download images that you will use in advance.
When creating local Registry, you need to run "docker run" first, and then push image to local Registry.
3.3 docker create -it
"docker create" is a command for creating container from image. You need to be careful with -it option.
If -it option is not specified, bash will be terminated and container will be stopped immediately.
$ docker create --name bash-without-it ubuntu:16.04 $ docker start -i bash-without-it $ # This is host machine's shell prompt. $ docker attach bash-without-it You cannot attach to a stopped container, start it first
If -i option is not specified, bash does not accept stdin.
$ docker create -t --name bash-without-i ubuntu:16.04 $ docker start -i bash-without-i root@35859c489ea1:/# ls # Type ls[RET] but no response
If -t option is not specified, pseudo-tty will no be created. TERM variable will be empty and prompt string will not be displayed.
$ docker create -i --name bash-without-t ubuntu:16.04 $ docker start -i bash-without-t uname # Type uname[RET] Linux ls # Type ls[RET] bin boot dev etc home lib lib64 media mnt opt proc root run sbin srv sys tmp usr var
If -it option is specified, bash is done normally.
$ docker create -it --name bash ubuntu:16.04 $ docker start -i bash root@f5fbe8daa835:/# uname Linux root@f5fbe8daa835:/# ls bin dev home lib64 mnt proc run srv tmp var boot etc lib media opt root sbin sys usr
3.4 docker start -i
"docker start" is a command for starting container.
If -i option is specified, attach to the container at the same time as starting the container with connecting stdin.
$ docker start -i <container>
The following command is almost same with "docker run", except that it returns to host machine between start and attach.
$ docker start <container> $ docker atttach <container>
There is -a option similar with -i option. If -a option is specified, attach to the container at the same time as starting the container without connecting stdin.
$ docker start -i <container>
The following command is almost same with "docker run", except that it returns to host machine between start and attach.
$ docker start <container> $ docker atttach --no-stdin <container>
4 Create your own image
This article will create image which has a emacs package with using ubuntu:16.04 as a base image.
4.1 Create your own image from container
Create container from ubuntu:16.04.
$ docker run -it --name ubuntu-1604-emacs ubuntu:16.04
This image does not have a emacs package.
root@cf4e53146385:/# emacs --version bash: emacs: command not found
After installing emacs, terminate bash and stop container.
root@cf4e53146385:/# apt update -y && apt install -y emacs && exit
Create image from container with "docker commit".
$ docker commit ubuntu-1604-emacs ubuntu-1604-emacs-image
Image was created.
$ docker images REPOSITORY TAG IMAGE ID CREATED SIZE ubuntu-1604-emacs-image latest 41716956f654 About a minute ago 546 MB ubuntu 16.04 f49eec89601e 3 weeks ago 129 MB
Create container from created image.
$ docker run -it ubuntu-1604-emacs-image
This image has a emacs container.
root@b91c82c0c976:/# emacs --version GNU Emacs 24.5.1 Copyright (C) 2015 Free Software Foundation, Inc. GNU Emacs comes with ABSOLUTELY NO WARRANTY. You may redistribute copies of Emacs under the terms of the GNU General Public License. For more information about these matters, see the file named COPYING.
4.2 Create your own image from Dockerfile
Create the following Dockefile.
$ cat Dockerfile FROM ubuntu:16.04 RUN \ apt update -y && \ apt install -y emacs CMD ["bash"]
Create image from Dockerfile with "docker build". Temporally container will be created.
$ docker build -t ubuntu-1604-emacs-dockerfile . Sending build context to Docker daemon 2.048 kB Step 1/3 : FROM ubuntu:16.04 ---> f49eec89601e Step 2/3 : RUN apt update -y && apt install -y emacs ---> Running in d7a592031026 WARNING: apt does not have a stable CLI interface. Use with caution in scripts. Get:1 http://archive.ubuntu.com/ubuntu xenial InRelease [247 kB] Get:2 http://archive.ubuntu.com/ubuntu xenial-updates InRelease [102 kB] Get:3 http://archive.ubuntu.com/ubuntu xenial-security InRelease [102 kB] <snip> Step 3/3 : CMD bash ---> Running in 77adc54aa247 ---> bcf7de949838 Removing intermediate container 77adc54aa247 Successfully built bcf7de949838
Image was created.
$ docker images REPOSITORY TAG IMAGE ID CREATED SIZE ubuntu-1604-emacs-dockerfile latest bcf7de949838 36 seconds ago 546 MB ubuntu-1604-emacs-image latest 41716956f654 34 minutes ago 546 MB ubuntu 16.04 f49eec89601e 3 weeks ago 129 MB
Create container from created image.
$ docker run -it ubuntu-1604-emacs-dockerfile
This image has a emacs container.
root@6ac693d1b24a:/# emacs --version GNU Emacs 24.5.1 Copyright (C) 2015 Free Software Foundation, Inc. GNU Emacs comes with ABSOLUTELY NO WARRANTY. You may redistribute copies of Emacs under the terms of the GNU General Public License. For more information about these matters, see the file named COPYING.
5 Access to container from external network
This article will access to Jenkins on container from external network. Jenkins will use 8080/tcp.
Docker has three network by default. If ommitinig –network option, bridge network will be used.
bridge | bridge network has a bridge names docker0. |
This will connect host machine's NIC with IP masquerade of | |
iptables (L3 layer). | |
This needs port forwarding for accessing from external network. | |
host | host network uses host machine's NIC apparently. |
External network cannot access to this. | |
none | none network does not create NIC. |
NIC of this article is as below.
eth0 | Host machine's NIC. IP address is 192.168.11.102/24. |
docker0 | The bridge which is created when starting docker. |
IP address is 172.17.0.1/16 assigned by bridge network. |
5.1 Use port forwarding on bridge network
Map 80/tcp on host machine to 8080/tcp on container. Omitting –network option specifies bridge network.
$ docker run -d -p 80:8080 jenkins
Accessing 80/tcp on host machine will display Jenkins.
http://192.168.11.102
5.2 Use the same network address of external network with user defined network
Create another bridge which is L2 layer. The following article will create bridge names br0.
Created bridge is as below.
br0 | This is a bridge independently of docker. |
IP address of br0 is 192.168.11.102/24. | |
IP address of eth0 is empty. |
Create network which has a br0 with "docker network create".
$ docker network create \ --driver=bridge \ --subnet=192.168.11.102/24 \ --gateway=192.168.11.102 \ -o "com.docker.network.bridge.enable_icc=true" \ -o "com.docker.network.bridge.enable_ip_masquerade=false" \ -o "com.docker.network.bridge.host_binding_ipv4=0.0.0.0" \ -o "com.docker.network.bridge.name=br0" \ -o "com.docker.network.driver.mtu=1500" \ br0_network
Create container that network is br0_network, IP address is 192.168.11.200 and DNS is 192.168.11.1. This DNS value will be used by embedded DNS server (127.0.0.11). /etc/resolv.conf on container does not have this DNS value but have nameserver entry to embedded DNS server (127.0.0.11).
$ docker run -d --network=br0_network --ip=192.168.11.200 \ --dns=192.168.11.1 jenkins
Accessing to 8080/tcp on container will display Jenkins.
http://192.168.11.200:8080
5.3 Problem with user defined network
Because docker might not have IPAM driver for using external DHCP server, using user defined network needs implementation of DHCP (Or just write entry to dhcpd.conf) independently of docker.
Though IP masquerade is false, L3 layer setting will be done. This will prevent bridge network working. If you need container without specifing ip, use host network instead of bridge network.
When specifiying multiple –dns option and first DNS server returns REFUSED, the embedded DNS server will not send query to second DNS server. The embedded DNS server will send query when DROP and REJECT. I don't know this is correct working but my Windows, Linux and MacOS will access to second DNS server when first DNS returns REFUSE.
6 Other command
docker <arg> is alias for docker image <arg> and docker container <arg>.
docker images | Show images. |
docker rmi <image> | Remove image. |
docker ps [-a] | Show containers without stopped ones. |
-a shows all containers. | |
docker stop <container> | Stop container. |
docker exec <container> <cmd> | Run other command on running container. |
"docker ps -q" shows only ID. The following command will stop all running containers.
$ docker stop $(docker ps -q)