Do a short recap on Docker/Containers/Images/build/pull/run. Repositories, Registries, Index.
Then looked at:
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)
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>
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)
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)
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.
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.
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
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
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.
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.
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.