Understanding container concepts & how to create a docker image using the docker cli.
Containers are self contained, immutable entities that include everything required to run a piece of software via a container runtime. Docker is a container runtime. It can run on different platforms. Containers are instances of a docker image. Docker images can be shared via push and pull commands with the docker cli, similar to git. Images are made up of layers. Each layer builds on the previous layer by modifying the image filesystem or metadata.
Containers run in isolation from each other, and any other processes running on the OS. This happens at the kernel in Linux by sandboxing processes and controlling their resource allocations via control groups (cgroups).
Containers are immutable. The have a read-only filesystem. If a container is restarted, the filesystem is the same as the very first time it was run. The files in a container are whatever is included in the docker image.
The Docker container runtime (also know as the Docker Engine) is available for Linux, macOS & Windows. Linux based containers can be run on any of these platforms. It is possible to run Windows containers on certain versions of Windows.
Images are made up of 1 or more layers. Different images can have the same layer in common. For example, an nginx and Apache image could both use centos
as the base image. When sharing images, it is only necessary to send the layer differences rather than the full image.
To test docker is installed & running ok, run this command:
$ docker --version
Docker version 1.12.6, build ae7d637/1.12.6
You can list images on you local machine.
$ docker images
To pull an image from Docker Hub, use the docker pull
command e.g.
$ docker pull golang:1.8.1-onbuild
Trying to pull repository docker.io/library/golang ...
sha256:93fe73ae67ed0f1391b49495bc6a21106617f61f16bbc61a885674d7174d8070: Pulling from docker.io/library/golang
10a267c67f42: Pull complete
fb5937da9414: Pull complete
9021b2326a1e: Pull complete
96109dbc0c87: Pull complete
57d8fbf72ff8: Pull complete
38d688423455: Pull complete
c9ade847cc74: Pull complete
5139017b86e5: Pull complete
Digest: sha256:93fe73ae67ed0f1391b49495bc6a21106617f61f16bbc61a885674d7174d8070
Status: Downloaded newer image for docker.io/golang:1.8.1-onbuild
You should now see this image in the list if you run docker images
again.
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
docker.io/golang 1.8.1-onbuild 3064d3aa065d 3 weeks ago 702.8 MB
A Docker image is essentially a snapshot of a container. When used with the docker run
command, they are used to create a running instance of a container.
To create a Docker image you need a Dockerfile. A Dockerfile is essentially a set of instructions that Docker uses to create the Docker image.
Example:
https://github.com/feedhenry/wit-docker-example
To create an image from this example, first clone it.
$ git clone https://github.com/feedhenry/wit-docker-example.git
Then build the image:
$ cd wit-docker-example
$ docker build -t wit/example .
Sending build context to Docker daemon 56.32 kB
Step 1 : FROM golang:1.8.1-onbuild
# Executing 3 build triggers...
Step 1 : COPY . /go/src/app
Step 1 : RUN go-wrapper download
---> Running in 3279aec53159
+ exec go get -v -d
Step 1 : RUN go-wrapper install
---> Running in 7906d9740f3c
+ exec go install -v
app
---> cdd1ecbfd0cd
Removing intermediate container 3279aec53159
Removing intermediate container 7906d9740f3c
Removing intermediate container 64c608365953
Successfully built cdd1ecbfd0cd
The image should now be listed, with the latest
tag.
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
wit/example latest cdd1ecbfd0cd 34 seconds ago 708.7 MB
Dockerfile Reference https://docs.docker.com/engine/reference/builder/
The repository contents:
├── Dockerfile
├── main.go
└── README.md
The Dockerfile:
FROM golang:1.8.1-onbuild
The 'parent' Dockerfile with ONBUILD
instructions
FROM golang:1.8
RUN mkdir -p /go/src/app
WORKDIR /go/src/app
# this will ideally be built by the ONBUILD below ;)
CMD ["go-wrapper", "run"]
ONBUILD COPY . /go/src/app
ONBUILD RUN go-wrapper download
ONBUILD RUN go-wrapper install
To run the image, use docker run
:
$ docker run -it --rm --name wit wit/example:latest
+ exec app
2017/06/06 11:09:02 starting on port 3000
To call the server that's running, we need to find the container IP Address. You can find this out by running this command in a new terminal/console window.
$ docker inspect --format='{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' wit
Then curl the /hello
endpoint
$ curl <ip address>:3000/hello
hello world
Try curl localhost to see what the response is:
$ curl localhost:3000/hello
To access the server from localhost, you need to expose the port.
$ docker run -it --rm --name wit -p 3000:3000 wit/example:latest
+ exec app
2017/06/06 11:09:54 starting on port 3000
Now try curling it on localhost again.
$ curl localhost:3000/hello
hello world
A 'docker machine' is a local or remote instance running docker. More info on setting one up can be found at https://docs.docker.com/machine/.
Deploying a container to a remote docker-machine can be done using the docker
cli. Instead of all commands running against your local machine, they run against the remote machine. Whenever you build an image, it is being built on the remote docker machine. If you pull an image, it gets pulled onto the remote docker machine.
Kubernetes is a system for automating deployment, scaling, and management of containerized applications. It groups containers that make up an application into logical units for easy management and discovery. If you have a kubernetes cluster, you can run docker containers in that cluster via kubernetes templates & the kubectl
cli. https://kubernetes.io/docs/user-guide/kubectl-overview/
If you have an OpenShift cluster (based on kubernetes), you can run docker containers in that cluster via openshift templates & the oc
cli. https://openshift.io/
Kubernetes & OpenShift templates reference the docker image to use when running a container. The image must already be available on the cluster nodes, or be available to pull down. In order to make our image available, we can push it to a public repository on Docker Hub.
You will need a Docker Hub account for this part. First, use docker tag
to let docker know what the remote url will be.
$ docker tag wit/example:latest <docker hub username>/example:latest
$ docker push <docker hub username>/example:latest
Once pushed, you can reference the image in the remote kubernetes/OpenShift cluster
$ oc new-project wit
$ oc run wit --image=<docker hub username>/example --port=3000
deploymentconfig "wit" created
The pod can be exposed via a service
& route
$ oc expose rc wit-1 --port=3000 --target-port=3000 --name=wit
$ oc expose service wit --name=wit
The exposed route
can be used to access the running container.
$ curl wit-wit.osm4.skunkhenry.com/hello
$ hello world