itentidock example from O'Reilly _Using Docker_
Python Shell
Switch branches/tags
Nothing to show
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Failed to load latest commit information.
app
Dockerfile
README.md
cmd.sh
docker-compose.yml

README.md

identidock

itentidock example app from

cover Using Docker by Adrian Mouat

Examples below are using boot2docker on Mac running OS X 10.10.3.

It might be helpful to refer to these Docker User Guide docs once you get stuck:

Step 1. Simple Hello World

Ref

Using this Dockerfile.

  • Example of using the code bundled inside the identidock image within the container.
docker build -t identidock .
DID=$(docker run -d -p 5000:5000 identidock)
curl $(boot2docker ip):5000 # expect Hello World!
docker rm -f $DID
  • Example of using the code in our current directory referenced as volume bind mounted in identidock container, occluding the code bundled inside the image.
DID=$(docker run -d -p 5000:5000 -v $(pwd)/app:/app identidock)
curl $(boot2docker ip):5000 # expect Hello World!
sed -i s/World/Docker/ app/identidock.py # undo this change after the test
curl $(boot2docker ip):5000 # expect Hello Docker!
docker rm -f $DID

Step 2 add uWSGI

Using this Dockerfile.

  • Start new uwsgi tagged instance of identidock docker image.
docker build -t identidock:uwsgi .
DID=$(docker run -d -p 9090:9090 -p 9191:9191 identidock:uwsgi)
curl $(boot2docker ip):9090          # expect Hello World!
curl $(boot2docker ip):9191          # expect JSON block of stats
docker logs $DID 2>&1 | grep WARNING # expect to get yelled at for using root
docker rm -f $DID

BTW Here are the images we have made at this point. Not that lastest is from step 1 and uwsgi is from step 2:

$ docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
identidock          uwsgi               cf36ee739e9c        12 minutes ago      767.2 MB
identidock          latest              fd04dbc88df1        43 minutes ago      765.1 MB

Step 3 Run uWSGI as someone other than root and auto-map ports

Using this Dockerfile run the container as uwsgi user and designate ports in Dockerfile instead of on the command line.

docker build -t identidock:user .
docker run identidock:uwsgi whoami
root
docker run identidock:user whoami
uwsgi
DID=$(docker run -d -P --name port-test identidock:user)
docker port port-test
9090/tcp -> 0.0.0.0:32768
9191/tcp -> 0.0.0.0:32769
curl $(boot2docker ip):32768
Hello World!

Step 4 Delegate app start to cmd shell script which determines environment first

Ref

Using this Dockerfile build and run a dev instance of identidock.

docker build -t identidock:cmd .
DID=$(docker run -e "ENV=DEV" -d -P identidock:cmd)
docker port $DID
5000/tcp -> 0.0.0.0:32782
9090/tcp -> 0.0.0.0:32783
9191/tcp -> 0.0.0.0:32784
# curl port 5000 in the container
curl $(boot2docker ip):32782
Hello World!
# there is nothing listening on 9090 in this container
curl $(boot2docker ip):32783
curl: (7) Failed to connect to 192.168.59.103 port 32783: Connection refused

Now stop that container and run a production instance.

docker rm -f $DID
DID=$(docker run -e "ENV=PROD" -d -P identidock:cmd)
docker port $DID
9191/tcp -> 0.0.0.0:32787
5000/tcp -> 0.0.0.0:32785
9090/tcp -> 0.0.0.0:32786
# there is nothing listening on 5000 in this container
curl $(boot2docker ip):32785
curl: (7) Failed to connect to 192.168.59.103 port 32785: Connection refused
# curl port 9090 in the container
curl $(boot2docker ip):32786
Hello World!
# shortcut
curl $(boot2docker ip):$(docker port $DID 9090 | cut -d: -f2)
Hello World!

The cut in the shortcut above is needed since docker port returns something like 0.0.0.0:9999. I there a better way to do that?

Step 5 Use docker-compose to launch container

Install docker-compose before continuing.

curl -o docker-compose -L https://github.com/docker/compose/releases/download/1.2.0/docker-compose-`uname -s`-`uname -m`
chmod 755 docker-compose
sudo mv docker-compose /usr/local/bin
docker-compose --help
Illegal instruction: 4

Oh no! It didn't work!

It turns out that you can pip install docker-compose to work around this.

brew update
brew install python
pip install docker-compose

Create a docker-compose.yml which looks like this.

---
identidock:
  build: .
  ports:
    - "5000:5000"
  environment:
    ENV: DEV
  volumes:
    - ./app:/app

Now, start up the container.

docker-compose up

Using docker-compose v1.2.0, I got a python traceback:

Successfully built bb9620f3a5b1
Attaching to identidock_identidock_1
Exception in thread Thread-1:
Traceback (most recent call last):
  File "/usr/local/Cellar/python/2.7.6_1/Frameworks/Python.framework/Versions/2.7/lib/python2.7/threading.py", line 810, in __bootstrap_inner
    self.run()
  File "/usr/local/Cellar/python/2.7.6_1/Frameworks/Python.framework/Versions/2.7/lib/python2.7/threading.py", line 763, in run
    self.__target(*self.__args, **self.__kwargs)
  File "/usr/local/lib/python2.7/site-packages/compose/cli/multiplexer.py", line 41, in _enqueue_output
    for item in generator:
  File "/usr/local/lib/python2.7/site-packages/compose/cli/log_printer.py", line 59, in _make_log_generator
    for line in line_generator:
  File "/usr/local/lib/python2.7/site-packages/compose/cli/utils.py", line 77, in split_buffer
    for data in reader:
  File "/usr/local/lib/python2.7/site-packages/docker/client.py", line 225, in _multiplexed_response_stream_helper
    socket = self._get_raw_response_socket(response)
  File "/usr/local/lib/python2.7/site-packages/docker/client.py", line 167, in _get_raw_response_socket
    self._raise_for_status(response)
  File "/usr/local/lib/python2.7/site-packages/docker/client.py", line 119, in _raise_for_status
    raise errors.APIError(e, response, explanation=explanation)
APIError: 500 Server Error: Internal Server Error ("http: Hijack is incompatible with use of CloseNotifier")

I'm not sure what that is from, but everything is working. A new image was built and a development version of the identidock app is up and running. Let's look around.

docker images
REPOSITORY              TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
identidock_identidock   latest              bb9620f3a5b1        42 seconds ago      767.5 MB

docker ps -l
CONTAINER ID        IMAGE                          COMMAND             CREATED             STATUS              PORTS                                        NAMES
9113a34dcce9        identidock_identidock:latest   "/cmd.sh"           5 minutes ago       Up 5 minutes        9090/tcp, 0.0.0.0:5000->5000/tcp, 9191/tcp   identidock_identidock_1

curl $(boot2docker ip):5000
Hello World!

docker-compose logs
Attaching to identidock_identidock_1
identidock_1 | Running Development Server
identidock_1 |  * Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)
identidock_1 |  * Restarting with stat
identidock_1 | 192.168.59.3 - - [26/Apr/2015 22:13:14] "GET / HTTP/1.1" 200 -
identidock_1 |  * Detected change in '/app/identidock.py', reloading
identidock_1 |  * Restarting with stat
identidock_1 | 192.168.59.3 - - [26/Apr/2015 22:14:46] "GET / HTTP/1.1" 200 -

Since we mapped our app directory as a volume in the container, we can make changes to identidock.py which will be picked up immediately. Try it.

Step 6 Link to dnmonster container and update app to generate images

Ref

Moving beyond 'Hello World!' now we'll update the app to call out to another web server to request a generated image for display. The webserver will be a linked container called dnmonster.

  • Update identidock.py to generate an html page and form
  • Update the Dockerfile to add requests library to the pip install layer.
  • Rebuild the image and pull the amouat/dnmonster image.
# rebuild image with 'link' tag
docker build -t identidock:link .
# automatically pull and run the image found on registry.hub.docker.com
docker run -d --name dnmonster amouat/dnmonster

The Dockerfile for that image is basically as follows. Note that it exposes port 8080.

FROM node:0.11
RUN apt-get update && apt-get install -yy libcairo2-dev \
    libjpeg62-turbo-dev libpango1.0-dev libgif-dev build-essential g++
RUN mkdir -p /usr/src/app
WORKDIR /usr/src/app
COPY package.json /usr/src/app/
RUN npm install
COPY ./src /usr/src/app
CMD [ "npm", "start" ]
EXPOSE 8080

Now create a container from the identidock:link image and link it to the newly started dnmonster container.

docker run -d -p 5000:5000 -e "ENV=DEV" --link dnmonster:dnmonster identidock:link

If you use exec -ti to run bash in the identidock container you can see that /etc/hosts has an entry for dnmonster automatically and you can ping it by name. Pretty cool.