Skip to content

Instantly share code, notes, and snippets.

@ipbabble
Last active April 28, 2016 00:51
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ipbabble/c7f231d6ebf596e61cd6 to your computer and use it in GitHub Desktop.
Save ipbabble/c7f231d6ebf596e61cd6 to your computer and use it in GitHub Desktop.
Deeper Docker

Intro

Do a short recap on Docker/Containers/Images/build/pull/run. Repositories, Registries, Index.

Then looked at:

Preparation

Can build a quick Fedora/HTTP Image from Dockerfile:

 # Base on the Fedora
 FROM fedora:latest
 MAINTAINER William Henry email ipbabble@gmail.com

 # Install the Dispatch
 RUN echo "Updating all fedora packages"; dnf -y update; dnf -y clean all
 RUN echo "Installing httpd"; dnf -y install httpd
 
 # Expose the default httpd port 80
 EXPOSE 80

 # Run the httpd
 CMD ["/usr/sbin/httpd", "-DFOREGROUND"]

Build and run:

 sudo docker build -t myrepo/fedora-httpd .
 sudo docker run -d myrepo/fedora-httpd
 sudo docker ps

You should see the container running something like this:

 CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS     NAMES
 95f13e5304a4        fedora-httpd        "/usr/sbin/httpd -DFO"   6 seconds ago       Up 6 seconds        80/tcp    awes...

However loading localhost in the browser doesn't seem to work. Let's stop and remove the container and try again.

 sudo docker stop 95f13e5304a4
 sudo docker rm 95f13e5304a4
 sudo docker run -d -p 80:80 fedora-httpd
 sudo docker ps
 
 CONTAINER ID        IMAGE               COMMAND                  CREATED              STATUS              PORTS    
 267ea0953787        fedora-httpd        "/usr/sbin/httpd -DFO"   About a minute ago   Up About a minute   0.0.0.0:80->80/tcp   

(NAMES column removed for space)

Inspect and format

Get container id:

 sudo docker ps

Use:

 sudo docker inspect <container-id>

IP Address:

 sudo docker inspect --format='{{.NetworkSettings.IPAddress}}' <container-id>

Port Mapping:

 sudo docker inspect --format='{{range $p, $conf := .NetworkSettings.Ports}} {{$p}} -> {{(index $conf 0).HostPort}} {{end}}' <container-id>
 sudo docker inspect --format='{{.NetworkSettings.Bridge}}' <container-id>
 sudo docker inspect --format='{{.ProcessLabel}}' <container-id>

CMD Vs ENTRYPOINT

Great article that also explains difference between CMD and ENTRYPOINT

 http://crosbymichael.com/dockerfile-best-practices.html

Main difference: CMD can be overridden by docker run. ENTRYPOINT can not ENTRYPOINT can take params from CMD. For example:

CMD = [ "--help" ]
ENTRYPOINT = [ "/usr/bin/redis" ]

Makes three points (from Crosby's article) regarding these commands:

  • Always use the array syntax when using CMD and ENTRYPOINT.
  • If you use the CMD syntax without the array, docker pre-pends /bin/sh -c to your command.
  • ENTRYPOINT and CMD are better together. (see the rethinkdb example)

Using Volumes & SELinux

SELinux provides extra protection for containers or from containers.

 sudo docker run -v /tmp/vol1:/data -it fedora:21 bash

Try to Edit/Touch the file /data/myfile and see it won't work if setenforce is on.

      sudo docker run -v /tmp/vol1:/data:z -it fedora:21 bash

Try again to edit. It works!

'z' says the container shares the namespace and can write to it. Also containers that use --volumes-from this container can also access the volume. By using 'Z' the volume will remain private to the data volume.

Also in the container:

 ls -alZ /data

Exit and look on the host in /tmp/vol1 and see the new file and it's data.

(Or variations on above)

Using -v and --privileged to launch a Docker client container

 Create a simple Dockerfile:
 FROM fedora:21

 # Update the system
 RUN yum -y update; yum -y clean all
 RUN yum -y install docker-io

Then build it and run it like :

 sudo docker run -v /var/run/docker.sock:/var/run/docker.sock -it myrepo/fedora-docker bash

Now run a Docker command:

 bash-4.2# docker images 
 2014/08/05 16:18:56 Get http:///var/run/docker.sock/v1.12/containers/json: dial unix /var/run/docker.sock: permission denied

That didn't work! SELinux denies. And chcon can't help on this one. So let's run in privileged mode:

 sudo docker run --privileged=true -v /var/run/docker.sock:/var/run/docker.sock -it myrepo/fedora-docker bash

Now run a few Docker commands:

 bash-4.2# docker images 
 bash-4.2# docker ps

Use Case: Running a CI build agent daemon in a container that, when it received a build job, would run another docker container on the same host to run that job. Basically it allows a docker container to execute shell scripts w/ docker builds and docker runs in them w/o having to do the whole docker-in-docker thing.

Data Volume

Create a directory in tmp on the container host. Bind it to the container runtime.

 sudo docker run -v /tmp/stuff:/data:z --name=datavol2 -it fedora:21 bash

In another shell docker run --volumes-from= container name

 sudo docker run -it --volumes-from=datavol2 fedora:21 bash

In 2nd shell create/touch a file. Look at file in first shell Look at file on host machine.

Mounting Devices Systemd - syslog and journalctl

Let's make our container's logging visible on the host through the syslog device:

sudo docker run -v /dev/log:/dev/log -i -t fedora:21 logger "SYSLOG-TEST Meetup Test1"
sudo journalctl -b | grep SYSLOG

Links

Look at the Dockerfile for the httpd again (from above) show the exposed port.

  more ~/docker-imgs/httpd/Dockerfile

Run the fedora/httpd container and give it a name:

 sudo docker run -itd --name=link-test myrepo/fedora-http

Run another container with a link to link-test

 sudo docker run -it --link=link-test:lt --name=linked fedora:21 bash

(fyi --name is never really needed above but it is good practice.)

 bash-4.3# env  
 bash-4.3# curl http://lt:80

Using --net=

Explaination from the man page:

Set the Network mode for the container: 'bridge': (DEFAULT) creates a new network stack for the container on the docker bridge 'none': no networking for this container 'container:<name|id>': reuses another container network stack 'host': use the host network stack inside the container

Create a Dockerfile with FROM fedora:21 and install net-tools package.

Look at the hosts ip stack with the docker0 bridge:

$ ifconfig 

Run the new fedora-net image:

sudo docker run -ti myrepo/fedora-net bash

See normal ip stack using bridge:

bash-4.3# ifconfig

Explain that the default for --net is "bridge" Now run with --net=host

 sudo docker run --net=host -ti fedora:21 bash
 bash-4.3# ifconfig

Notice all the interfaces are present. Discuss how this just removes the bridging layer normally present and how this is a good example of how Docker is just siloing off processes on the same host / kernel.

Using docker run -b to us an existing network bridge

Suppose docker0 bridge doesn't work with our network topology? How do we change the bridge? Run the docker daemon and attache to a preexisting bridge.

 TBD add example here.

Private Registry

Install and start a private registry on host:

 sudo yum -y install docker-registry
 sudo systemctl start docker-registry

Lets look at what images we have:

 sudo docker images

Now let's push an image to the registry:

 sudo docker push localhost.localdomain:5000/myrepo/fedora-http

That didn't work! Why? Expalin that though I'm specifying the right image and explicitly pointing to the private registry we need to tag the image with the registry:

 sudo docker tag myrepo/fedora-http localhost.localdomain:5000/myrepo/fedora-http
 sudo docker push localhost.localdomain:5000/myrepo/fedora-http

Now it works. Might want to Docker stop, rm amd rmi all the containers/images myrepo/fedora-http related and then:

 sudo docker pull localhost.localdomain:5000/myrepo/fedora-http

Success! Explain they may need to retag it back to something useful like fedora-http.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment