Wednesday, March 8, 2017

Docker Build Your Own Image

Before moving forward make sure, you have up and running Docker service

In this example, I will be using flask-app 

Ref: https://training.docker.com/user/consume/course_pathway/7c7fcfcb-8e2f-32dc-9531-1db82f671120/92/aa9e230a-6617-3e0b-a8ba-d6f6245aee0a?complete=0&tab=overview

1) Create directory called flask-app

mkdir flask-app
cd flask-app


2) Create a file app.py

cat > app.py

from flask import Flask, render_template
import random

app = Flask(__name__)

# list of cat images
images = [
    "http://ak-hdl.buzzfed.com/static/2013-10/enhanced/webdr05/15/9/anigif_enhanced-buzz-26388-1381844103-11.gif",
    "http://ak-hdl.buzzfed.com/static/2013-10/enhanced/webdr01/15/9/anigif_enhanced-buzz-31540-1381844535-8.gif",
    "http://ak-hdl.buzzfed.com/static/2013-10/enhanced/webdr05/15/9/anigif_enhanced-buzz-26390-1381844163-18.gif",
    "http://ak-hdl.buzzfed.com/static/2013-10/enhanced/webdr06/15/10/anigif_enhanced-buzz-1376-1381846217-0.gif",
    "http://ak-hdl.buzzfed.com/static/2013-10/enhanced/webdr03/15/9/anigif_enhanced-buzz-3391-1381844336-26.gif",
    "http://ak-hdl.buzzfed.com/static/2013-10/enhanced/webdr06/15/10/anigif_enhanced-buzz-29111-1381845968-0.gif",
    "http://ak-hdl.buzzfed.com/static/2013-10/enhanced/webdr03/15/9/anigif_enhanced-buzz-3409-1381844582-13.gif",
    "http://ak-hdl.buzzfed.com/static/2013-10/enhanced/webdr02/15/9/anigif_enhanced-buzz-19667-1381844937-10.gif",
    "http://ak-hdl.buzzfed.com/static/2013-10/enhanced/webdr05/15/9/anigif_enhanced-buzz-26358-1381845043-13.gif",
    "http://ak-hdl.buzzfed.com/static/2013-10/enhanced/webdr06/15/9/anigif_enhanced-buzz-18774-1381844645-6.gif",
    "http://ak-hdl.buzzfed.com/static/2013-10/enhanced/webdr06/15/9/anigif_enhanced-buzz-25158-1381844793-0.gif",
    "http://ak-hdl.buzzfed.com/static/2013-10/enhanced/webdr03/15/10/anigif_enhanced-buzz-11980-1381846269-1.gif"
]

@app.route('/')
def index():
    url = random.choice(images)
    return render_template('index.html', url=url)

if __name__ == "__main__":
    app.run(host="0.0.0.0")


#########################


3) Create a file called requirements.txt

cat > requirements.txt

Flask =0.10.1


4) Create directory templates and then file index.html in it

mkdir templates
cat  > templates/index.html

<html>
  <head>
    <style type="text/css">
      body {
        background: black;
        color: white;
      }
      div.container {
        max-width: 500px;
        margin: 100px auto;
        border: 20px solid white;
        padding: 10px;
        text-align: center;
      }
      h4 {
        text-transform: uppercase;
      }
    </style>
  </head>
  <body>
    <div class="container">
      <h4>Cat Gif of the day</h4>
      <img src="{{url}}" />
      <p><small>Courtesy: <a href="http://www.buzzfeed.com/copyranter/the-best-cat-gif-post-in-the-history-of-cat-gifs">Buzzfeed</a></small></p>
    </div>
  </body>
</html>


5) Write a Dockerfile, create a file called Dockerfile in flask-app directory with following content

FROM alipine:3.5

RUN apk add --update py2-pip

COPY requirements.txt /usr/src/app/
RUN pip install --no-cache-dir -r /usr/src/app/requirements.txt

COPY app.py /usr/src/app/
COPY templates/index.html /usr/src/app/templates

EXPOSE 5000

CMD ["python", "/usr/src/app/app.py"]


6) Verify Dockerfile

##out base image
FROM alpine:3.5

# Install python and pip
RUN apk add --update py2-pip

# Install python modules needed by the python app
COPY requirements.txt /usr/src/app/
RUN pip install --no-cache-dir -r /usr/src/app/requirements.txt

# copy files required for the app to run
COPY app.py /usr/src/app/
COPY templates/index.html /usr/src/app/templates/

# tell the port number the container should expose
EXPOSE 5000

# run the application
CMD ["python", "/usr/src/app/app.py"]


7) Build the image (make sure you are in flask-app where Dockerfile exists)

docker build -t manoj/myfirstapp .

It's output in last lines will be 

Removing intermediate container 65fce60d1108
Step 8/8 : CMD python /usr/src/app/app.py
 ---> Running in 59d87e1975ed
 ---> af2bf7953190
Removing intermediate container 59d87e1975ed
Successfully built af2bf7953190

8) Now its time to run your own image

docker run -p 8888:5000 --name myfirstapp manoj/myfirstapp

8888 is the port will be running on Docker Host and 5000 port which we exposed in container


Output should be like

 docker run -p 8888:5000 --name myfirstapp manoj/myfirstapp

 * Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)


9) Now try browsing http://docker-host:8888


10) Its time push your repository to Docker Hub if you want

1st login to docker using command line

docker login --username=manojXXXX

this will prompt for password, enter password to connect to you account


11) As login is successful, We can tag our image to our docker username and change its path similar to our docker hub account like

docker tag manoj/myfirstapp manojXXXX/flask-app


12) Now we can push our image to Docker Hub, with latest tag

docker push manojsamtani/flask-app:latest

Output should be like

The push refers to a repository [docker.io/manojsamtani/flask-app]
806f2b9df705: Pushed 
8b394632d523: Pushed 
decd7faa1c3f: Pushed 
3cb442886a35: Pushed 
f18037a76d54: Pushed 
23b9c7b43573: Pushed 
latest: digest: sha256:5a1f8cf7518c532867a835a225bbe1256cb1baaec06029093ae112089765efd2 size: 1572


13) Now we can stop/remove containers locally

docker stop myfirstapp

docker rm myfirstapp

or

docker rm -f myfirstapp

Tuesday, March 7, 2017

Docker : Static Website

Before moving forward make sure, you have up and running Docker service

1) Run a static website in a container

docker run -d seqvence/static-site

So, what happens when you run this command?Since the image doesn't exist on your Docker host, the Docker daemon first fetches it from the registry and then runs it as a containerThe -d flag enables detached mode, which detaches the running container from the terminal/shell and returns your prompt after the container starts

2) Verify if container in running state

docker ps

CONTAINER ID    IMAGE    COMMAND    CREATED   STATUS    PORTS   NAME

Sb3b30fab0bc2        seqvence/static-site   "/bin/sh -c 'cd /u..."   5 seconds ago       Up 4 seconds        80/tcp, 443/tcp     wizardly_hypatia

3) But running container like in step 1) will not expose ports running in container to host machine. So, we need mention following flags for mapping/publish container ports on Docker Host

  • -d will create a container with the process detached from our terminal
  • -P will publish all the exposed container ports to random ports on the Docker host
  • -e is how you pass environment variables to the container
  • --name allows you to specify a container name
  • AUTHOR is the environment variable name and Your Name is the value that you can pass
docker run --name static-site -e AUTHOR="Your Name" -d -P seqvence/static-site

4) Now run below command to see how ports are published on docker host

docker port static-site443/tcp -&gt; 0.0.0.0:3276880/tcp -&gt; 0.0.0.0:32769

5) Try running http://docker-host:32768

6) If we need to map/publish custom host port to the container web server. Try running site 2 at the same time with custom port

docker run --name static-site-2 -e AUTHOR="Manoj Kumar" -d -p 8888:80 seqvence/static-site


docker ps

CONTAINER ID    IMAGE     COMMAND    CREATED       STATUS         PORTS          NAMES
c5d9d6bc66d1        seqvence/static-site   "/bin/sh -c 'cd /u..."   3 seconds ago       Up 3 seconds        443/tcp, 0.0.0.0:8888-&gt;80/tcp                   static-site-2

7) Try running http://docker-host:8888

NOTE: If you have stopped container and trying to start container again with different environment variable, if will through conflict as container already created and in stopped state. If you want to pass more/updated environment variables, 1st remove container and start again



Tuesday, February 28, 2017

Docker Basic Commands

Commands which are available to use in Docker to play with images or containers

## Download/Pull an image

docker pull alpine   ## alpine is an images located in local or docker hub repository

## List Docker images available locally

docker images

## Run Docker images

docker run alpine ls -l     #run command will look for image alpine locally if does not exist it will pull from docker hub, creates container and start/run a command in that container

docker run alpine echo "hello from alpine"

docker run alpine /bin/sh

Wait, nothing happened! Is that a bug? Well, no. These interactive shells will exit after running any scripted commands, unless they are run in an interactive terminal - so for this example to not exit, you need to docker run -it alpine /bin/sh

## List running containers

docker ps

## List all containers we ran

docker ps -a

## Run a container with attached tty

docker run -it alpine /bin/sh

This will drop you at /bin/sh shell in container (with tty) where you can run any command as similar to on OS

docker run -it alpine /bin/sh
/ # df -h
Filesystem                Size      Used Available Use% Mounted on
none                     18.1G      1.8G     15.3G  11% /
tmpfs                   496.2M         0    496.2M   0% /dev
tmpfs                   496.2M         0    496.2M   0% /sys/fs/cgroup
/dev/mapper/dockertest--vg-root
                         18.1G      1.8G     15.3G  11% /etc/resolv.conf
/dev/mapper/dockertest--vg-root
                         18.1G      1.8G     15.3G  11% /etc/hostname
/dev/mapper/dockertest--vg-root
                         18.1G      1.8G     15.3G  11% /etc/hosts
shm                      64.0M         0     64.0M   0% /dev/shm
tmpfs                   496.2M         0    496.2M   0% /proc/kcore
tmpfs                   496.2M         0    496.2M   0% /proc/timer_list
tmpfs                   496.2M         0    496.2M   0% /proc/timer_stats
tmpfs                   496.2M         0    496.2M   0% /proc/sched_debug
tmpfs                   496.2M         0    496.2M   0% /sys/firmware


## Inspect any image/container. INSPECT will Return low-level information on a container or image in JSON format

docker inspect alpine

Terminologies

  • Images - The file system and configuration of our application which are used to create containers
  • Containers - Running instances of Docker images — containers run the actual applications. A container includes an application and all of its dependencies. It shares the kernel with other containers, and runs as an isolated process in user space on the host OS
  • Docker daemon - The background service running on the host that manages building, running and distributing Docker containers
  • Docker client - The command line tool that allows the user to interact with the Docker daemon
  • Docker Hub - A registry of Docker images. You can think of the registry as a directory of all available Docker images

Docker : failed to get default registry endpoint from daemon, permission denied

If you are getting error while running docker commands by non root user like


Warning: failed to get default registry endpoint from daemon (Got permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock: Get http://%2Fvar%2Frun%2Fdocker.sock/v1.26/info: dial unix /var/run/docker.sock: connect: permission denied). Using system default: https://index.docker.io/v1/
Got permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock: Post http://%2Fvar%2Frun%2Fdocker.sock/v1.26/images/create?fromImage=alpine&tag=latest: dial unix /var/run/docker.sock: connect: permission denied


Add the non-root-user to group docker by updating /etc/group file or by running following command


usermod -aG docker non-root-user

Docker Installation On Ubuntu 16.04

This post is about installation of Docker on Ubuntu 16.04 (must be 64-bit version)

Pre-requisites:

1) Download Ubuntu 16.04 (http://releases.ubuntu.com/16.04/ubuntu-16.04.2-server-amd64.iso)

2) Install Ubuntu 16.04 (https://help.ubuntu.com/lts/installation-guide/amd64/install.en.pdf)

3) Internet connection available to update and install docker packages and its dependencies


Steps to install Docker:

apt-get update

apt-get install -y --no-install-recommends linux-image-extra-$(uname -r) linux-image-extra-virtual


NOTE : linux-image-extra-* allow docker to use the aufs storage drivers

Ref AUFS -> http://www.thegeekstuff.com/2013/05/linux-aufs/


## Allow apt to use/communicate a repository over HTTPS

apt-get install -y --no-install-recommends apt-transport-https ca-certificates curl software-properties-common



## Add Docker official GPG Key

curl -fsSL https://apt.dockerproject.org/gpg | sudo apt-key add -

## Verify that the key ID is 58118E89F3A912897C070ADBF76221572C52609D

apt-key fingerprint 58118E89F3A912897C070ADBF76221572C52609D

## Add Docker stable repository

add-apt-repository "deb https://apt.dockerproject.org/repo/ubuntu-$(lsb_release -cs) main"

## Install Docker

## update repositories to get the latest packages available to install

apt-get update

## Installing Docker enginer

apt-get -y install docker-engine

## Verify docker is installed correctly

docker run hello-world

It's output should be like


docker run hello-world
Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
78445dd45222: Pull complete 
Digest: sha256:c5515758d4c5e1e838e9cd307f6c6a0d620b5e07e6f927b07d05f6d12a1ac8d7
Status: Downloaded newer image for hello-world:latest

Hello from Docker!
This message shows that your installation appears to be working correctly.

To generate this message, Docker took the following steps:
 1. The Docker client contacted the Docker daemon.
 2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
 3. The Docker daemon created a new container from that image which runs the
    executable that produces the output you are currently reading.
 4. The Docker daemon streamed that output to the Docker client, which sent it
    to your terminal.

To try something more ambitious, you can run an Ubuntu container with:
 $ docker run -it ubuntu bash

Share images, automate workflows, and more with a free Docker ID:
 https://cloud.docker.com/

For more examples and ideas, visit:
 https://docs.docker.com/engine/userguide/



Yay!! You are ready to go with Docker containerization :-)