Docker
Table of Contents
Install docker
package and start the service by
systemctl start docker systemctl enable docker
We can build Debian image easily on Arch:
mkdir jessie-chroot # debootstrap jessie ./jessie-chroot http://http.debian.net/debian/ # cd jessie-chroot # tar cpf - . | docker import - debian # docker run -t -i --rm debian /bin/bash
Re-launch a stopped container can be done by docker start
<container>
and will be detached by default if it is run by that.
You can assign a name to the container so that you can better remember and reference it.
1 Compose
It is installed seperately with docker.
It must be run inside the folder containing docker-compose.yml
Commands
- docker-compose up: up the service. It will not exit. Use C-c to exit
and the
docker-compose down
command will be sent.- The second time you up the compose, it will not up, but update current. If all current are up to date, nothing will happen.
- docker-compose up -d: up the service and exit. You need to shutdown it maually
- docker-compose down: shutdown the services
A sample compose file:
version: '2' services: srcml-server-container: image: "lihebi/srcml-server" helium: image: "lihebi/arch-helium" tty: true volumes: - data:/data benchmark-downloader: # this is used to download benchmarks to the shared volume image: "lihebi/benchmark-downloader" tty: true volumes: - data:/data volumes: # create a volume with default data:
1.1 service
A service is a container. Setting tty to true to prevent it from
stopping. That is the same effect when you pass -t
to docker run
.
The containers can be seen by docker ps, with names prefixed and
suffixed by compose_XXX_1
Change to the container will not preserve after the compose down. The containers will be deleted. Next up will create new containers.
1.2 TODO volumes
Under any volume, if external
option is set to true
, docker
compose will find it outside, and signal error if it does not exist.
1.3 TODO network
Once the compose is up, docker create a bridge network called
compose_default
. All services (containers) are attached to that.
2 Network
- docker network ls
- docker network inspect <network-name>
3 Volume
A volume must be locally available if you create a local
volume.
3.1 Create Volume
You can create a volume like this:
docker volume create hello
Volumes can also be created upon creating a container.
3.2 Mount volume to a container
You have to mount at the time you create the container. You cannot remount anything to it without commiting it to an image and create again.
docker run -v /mnt <image> docker run -v my-named-vol:/mnt <image> docker run -v /absolute/path/to/host/local/path:/mnt/in/container <image>
If only inner path is provided, the volume will still be created, but
with a long named directory under /var/lib/docker/volumes
.
3.3 Manipulate Volume
The volumes will never be automatically deleted, even if the container is deleted.
3.3.1 TODO Will it be updated or not?
docker volume inspect <volume-full-name> docker volume ls docker volume prune # remove all unused volumes
4 General operations
- docker images
- list images
- docker images <name>
- list images whose name is "name" (can have different) tags
- docker run [option] <image> /bin/bash
- run a fresh container based on the image.
- -i
- interactive
- -d
- detach (opposite to -i)
- -t
- assign a tty. Even when using -d, you need this.
- -p <port>
- export the port <port> of the container. The host
port will be randomly assigned. Running
docker ps
will show the port binding information. If the port is not set when running a container, you have to commit it, and run it again to assign a port or another port. - -v /volumn
- create a mount at /volumn
- -v /local/dir:/mnt
- mount local dir to the /mnt in
container. The default is read-write mode, if you want read
only, do this:
-v /local/dir:/mnt:ro
. The local dir must be ABSOLUTE path.
- docker exec <ID> echo "hello"
- run some command with arguments on the already run container <ID>
- ID can be the UUID or container name
- you can use -it as well, e.g. docker exec -it <ID> /bin/bash
- docker start <ID>
- start an already stopped container
- docker diff <ID>
- show the difference made from the base image
- docker commit <ID> lihebi/my-container
- create a new image based on the container <ID>
- docker login
- login so that you can push
- docker push lihebi/my-container
- push to docker hub
- docker pull lihebi/my-container
- pull from the internet
Alternatively, you can write a Dockerfile to specify how to build a image.
FROM ubuntu 15.04 RUN ech o"hello" > /tmp/newfile
In the folder containing Dockerfile, run to build the image:
docker build -t my-ubuntu .
use –no-cache to avoid using cache
- docker history <image>
- show which layers are used to create <image>
4.1 Docker stop
docker stop will send SIGTERM to the app, then wait for it to stop. The default wait time is 10 seconds. You can change this by
docker stop -t 1 <container-ID>
This will change the timeout to be 1 second.
The reason for a container to resist stopping may be it ignores the SIGTERM request. Python did this, so for a python program, you should handle this signal yourself:
import sys import signal def handler(signum, frame): sys.exit(1) def main(): signal.signal(signal.SIGTERM, hanlder) # your app
Next thing is the entry point and commands. If you use shell form, it is started by sh -c, and shell will not pass the signal to the app either. So change it to json form.
Finally, docker stop
tries to terminate the app gracefully by
sending SIGTERM, you can choose to force kill using docker kill
5 Remove sudo
sudo groupadd docker sudo gpasswd -a ${USER} docker sudo service docker restart newgrp docker
6 Dockerfile
I'm trying a docker file for srcml container.
FROM debian RUN apt-get -y update & apt-get install -y libarchive-dev libcurl4-openssl-dev RUN wget http://131.123.42.38/lmcrs/beta/srcML-Ubuntu14.04-64.deb srcml.deb RUN dpkg -i srcml.deb
6.1 Commands
- FROM: a base image
- ENV key=value
- ADD:
ADD <src> .. <dst>
The difference from copy:- ADD allows src to be url
- ADD will decompress an archive
- COPY:
COPY <src> .. <dst>
all srcs on the local machine will be copied to dst in the image. The src can use wildcards. The src cannot be out of the current build directory, e.g...
is not valid. - USER:
USER daemon
The USER instruction sets the user name or UID to use when running the image and for any RUN, CMD and ENTRYPOINT instructions that follow it in the Dockerfile. - WORKDIR: The WORKDIR instruction sets the working directory for any
RUN, CMD, ENTRYPOINT, COPY and ADD instructions that follow it in
the Dockerfile
- if it does not exist, it will be created
- it can be used multiple times, if it is relative, it is relative to the previous WORKDIR
- ENTRYPOINT ["executable", "param1", "param2"]: configure the container to be run as an executable.
7 TODO Docker hub
When pushing and pulling, what exactly happens?
docker tag local-image lihebi/my-image docker push lihebi/my-image
8 Tricks
Stop all containers
docker stop $(docker ps -a -q)
Remove all containers (will not remove non-stopped ones, but give errors)
docker rm $(docker ps -a -q)
9 Trouble Shooting
9.1 I have to type double C-p to take effect
C-p C-q
is the default binding for detaching a container. This
blocks C-p, I have to type it twice, must change. In
~/.docker/config.json
, add:
{ "detachKeys": "ctrl-],ctrl-[" }
Restart docker daemon to take effect. This can also be set by
--detach-keys
option.
9.2 Docker exec tty is not a real tty
I cannot connect to emacs server through emacsclient -t, and error message is terminal is not found. You can not open tmux also. But the problem does not appear when using docker run command.
The solution is when starting a exec command, use script to run bash:
docker exec -it my-container script -q -c "/bin/bash" /dev/null docker exec -it my-container env TERM=xterm script -q -c "/bin/bash" /dev/null
The TERM is not necessary here because in my case docker always set it to xterm. I actually change it to screen-256color in my bashrc file to get the correct colors.