Docker: Difference between revisions
formatting |
|||
| Line 136: | Line 136: | ||
=== Dynamic Linking === | === Dynamic Linking === | ||
Containers can be linked together by creating a docker network. This is similar to a private network between two or more containers. | |||
To create a network and use it: | |||
{{highlight|lang=terminal|code= | |||
# docker network create example | |||
# docker run --rm -ti --net=example ubuntu bash | |||
}} | |||
Unlike linking in the previous section, container names are looked up using the docker DNS server. Starting and restarting containers will not break lookups since the DNS will always have the most up to date information (verses the static /etc/hosts file that gets generated on startup). | |||
Docker networks can be listed using {{code|docker network ls}} and its configuration as JSON using {{code|docker network inspect example}}. | |||
== Other Notes == | == Other Notes == | ||
Revision as of 04:13, 7 October 2017
Docker is a tool that allows applications inside sandboxed system environments called containers. It allows the user to reliably build a system environment including all required dependencies for an application. Docker provides containers with additional services such as network access, volume management, and resource limits. Unlike a traditional virtual machine, applications running on Docker will have a lighter footprint since applications run natively on the host's kernel.
Installation
Install docker using your package manager and then start the service.
On a Fedora distro (https://docs.docker.com/engine/installation/linux/docker-ce/fedora/#install-using-the-repository):
# dnf config-manager --add-repo https://download.docker.com/linux/fedora/docker-ce.repo
# dnf install docker-ce
# systemctl start docker
If installed properly, the docker hello-world command should work without issue.
# docker run hello-world
To play with docker, you will need to run things as root or be part of a group that has access to docker's socket.
See more here: https://docs.docker.com/engine/installation/linux/linux-postinstall/
Introduction
Images and Starting & Stopping Containers
An image contains all the necessary files to start an application. This includes all libraries, system files, and configuration files. An image should only contain just enough files to get the application working.
To list all images on your system:
# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
ubuntu latest 2d696327ab2e 2 weeks ago 122MB
alpine latest 76da55c8019d 3 weeks ago 3.97MB
hello-world latest 05a3bd381fc2 3 weeks ago 1.84kB
To create a container, start a program with one of these images using the docker run command. A few common arguments that are passed to docker run are:
-ti- terminal interactive (for interactive shells only)-d- start container detached; usedocker attach <image id or name>to attach.--name- provides a name rather than the random one that is generated.--rm- removes the container after it stops (ie. the container application (in this example the shell) exits)
For example, to start a bash shell in the ubuntu image:
# docker run -ti --rm ubuntu:latest bash
root@c148fbe71597:/# cat /etc/lsb-release
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=16.04
DISTRIB_CODENAME=xenial
DISTRIB_DESCRIPTION="Ubuntu 16.04.3 LTS"
You can see all running docker containers using the docker ps command. Common arguments to docker ps are:
-a- To see all containers including ones that have stopped-l- Print the last stopped container
# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
3ab813a72c70 ubuntu:latest "bash" 5 minutes ago Exited (130) 5 minutes ago agitated_dubinsky
2c4251af3005 alpine:latest "bash" 6 minutes ago Created eager_murdock
d9f2d1a0025c hello-world "/hello" 29 minutes ago Exited (0) 29 minutes ago musing_lewin
Docker containers can be referenced either by their container ID (which is a hash), or the randomly generated name.
A stopped container can be 'saved' back into an image using the docker commit command. There are two ways to go about this:
Manually commit the container ID (the hash), and then tag the image ID with an image name.
# docker commit <container id>
returns <image id>
# docker tag <image id> <image tag>
|
Or, commit the container using the randomly generated name and the image name.
# docker commit <container name> <image tag>
returns <image id>
|
Dealing with Stopped Containers
A container is stopped if all processes in the container terminates (whether intentionally, segfaults, or if a stop/kill signal was sent to it).
To stop a running container, use either the docker stop or docker kill commands.
A stopped container can also be started again using docker start. Interactive commands (like a bash shell) will require the -ai flags.
Troubleshooting a stopped container can be done by viewing any generated output generated by the container with the docker log command. While all text output generated by a container is logged by docker, it is still a good idea to rely on file logs for performance (docker log can be slow).
Networking
Docker provides networking to containers by providing something similar to a port forwarding between the host and the container. Inside port and outside port mappings are provided by the -p in:out/proto argument when starting a container.
The inside port is required. If no outside port is provided, docker will use the next available port on the host system. If no protocol is provided, docker will use TCP.
For example:
docker run --rm -ti -p 80:8080 web-server bash
A service listening on TCP port 80 inside the container will be accessible through TCP port 8080 on the host.
Linking
Docker provides a way for containers to 'link' to other containers on the same host. By linking one container to another, applications can talk to other applications in a separate container directly. When starting a container linked to another container, Docker will automatically update the /etc/hosts file and set up networking such that applications can talk to the other container directly without requiring traffic needing to route through the host.
Example:
On the 'server':
# docker run -ti --rm --name server ubuntu bash
root@85bdf83d4477:/# cat /etc/hosts
127.0.0.1 localhost
::1 localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
172.17.0.2 85bdf83d4477
|
On the 'client':
# docker run --rm -ti --link server --name client ubuntu bash
root@60e2d5ad2dbc:/# cat /etc/hosts
127.0.0.1 localhost
::1 localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
172.17.0.2 server 85bdf83d4477
172.17.0.3 60e2d5ad2dbc
|
The client can connect to 'server' directly by hostname.
This may be brittle, especially if containers are stopped/restarted anytime in the future separately.
Dynamic Linking
Containers can be linked together by creating a docker network. This is similar to a private network between two or more containers.
To create a network and use it:
# docker network create example
# docker run --rm -ti --net=example ubuntu bash
Unlike linking in the previous section, container names are looked up using the docker DNS server. Starting and restarting containers will not break lookups since the DNS will always have the most up to date information (verses the static /etc/hosts file that gets generated on startup).
Docker networks can be listed using docker network ls and its configuration as JSON using docker network inspect example.
Other Notes
To detach from a container, use the key combination Ctrl+P Ctrl+Q.
To run another program in an existing container, use the docker exec command with the same commands as run.
Don't fetch dependencies when containers start. Instead, make it part of the image.
Resource constraints: docker run --memory max-memory docker run --cpu-shares (relative to other containers) docker run --cpu-quota (limit in general)
Tags if not provided will be 'latest'
Usage Reference
| Command | Description |
|---|---|
docker images
|
Lists docker images that you created or pulled using docker pull
|
docker pull
|
Pulls a docker image from a registry (can be from docker.io or a private registry)
|
docker run
|
Runs a command in a container. Eg. docker run alpine ls -l
|
docker ps
|
Lists containers that are running.
Pass |
docker port
|
shows the port mapping between the container and the host. |
docker stop
|
Stop a container (By sending SIGSTOP?) |
docker kill
|
Stops a container (By sending SIGKILL?) |
docker rm
|
Removes a container. Use -rf to stop and remove.
|
Creating an Image
To create an image:
- Create a directory containing any custom files
- Create a
Dockerfilein the directory. - Run
docker buildto build the image
Dockerfile
The docker file should a the minimum contain:
# The base image to use
FROM baseimage:version
# What to run when the image is started. This can contain any number of RUN or COPY commands
RUN yum install any-dependencies
# Expose any ports that are required
EXPOSE 80
# run the application
CMD ["python", "/some/app.py"]
Deploying an Application
Use Docker Swarm mode to deploy an application that relies on multiple services where each is a separate docker instance.
The swarm file lets you define each server that is part of the application.
See more at https://github.com/docker/labs/blob/master/beginner/chapters/votingapp.md
Questions
- How are updates to the base image done? Does it automatically update containers relying on it? Or will containers need to be rebuilt again?
- Images are supposed to be immutable. When launching the image, any data that needs to be persistent must be externally provided with
-v outside/path:inside/path. When the base image is updated (say, CentOS 7.2 to CentOS 7.3), all images relying on it will need to be rebuilt from the Dockerfile. The resulting image is then used to 'relaunch' the container.
- Images are supposed to be immutable. When launching the image, any data that needs to be persistent must be externally provided with
- How is data kept persistent? Does it need to be copied out/in every time it is to be rebuilt?
- Persistent data should be saved outside of the container using the
-v outside/path:inside/path.
- Persistent data should be saved outside of the container using the
- NFS access from the container?
- You can mount a NFS share. But anything that requires a domain trust (like domained accounts) might not be feasible.
- Domain trust - is it the same as a regular VM?
- May not be feasible without hard coding some credentials in the dockerfile. Application based LDAP lookups with a binding account should still work.
Could it be used for...
- dictd (probably easily)
- WebCat (swarm tomcat + MySQL?)
- ftp (Requires NFS)
- compute balancer
- firewall manager (swarm apache + MySQL)