Skip to main content

Docker

#development/docker

https://www.youtube.com/watch?v=fqMOX6JJhGo

Containers

Are running instances of images that are isolated and have own environments and sets of processes

a container only lives as long as the process inside it runs

Images

An image is a package, template, plan.

Used to create one or more containers.

Commands

Containers

docker run

  • docker run nginx start a container

/docker run attached/detatched/

docker run kodekloud/simple-webapp

running this command means its in attached mode meaning you are attached to the console or stout of console container

ctrl+c exits back to prompt

to run in detatched mode:

docker run -d kodekloud/simple-webapp runs in the background go back to. your prompt imediatley

docker ps to view container

docker attach container-id or container-name to attach to container later

/tags/

docker run redis:4.0 You can target different versions of containers reds:4.0 4.0 is called a tag.

if no tag enteres latest is assumed.

dockerhub lists all supported tags

/interactive mode and terminal/

by default docker containers dont listen to standard input - it attaches to console but doesnt wait for input it runs in non interactive mode.

docker run -i kodekloud/simple-prompt-docker runs interactive mode

docker run -it kodekloud/simple-prompt-docker attached to terminal and interactive mode

/port mapping/

how does a user access an application? what IP do I use to access from webbrowser?

  1. use docker container IP - only accessible on docker host
  2. use docker host IP - docker run -p 80:5000 kodekloud/simple-webapp - lets you run multiple instances

docker run -p hostport:containerport kodekloud/simple-webapp

$ docker run kodekloud/webapp
* Running on http://0.0.0.0:5000

image-2020062513816055

$ docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 2a32e68ecac1 nginx:alpine "/docker-entrypoint.…" 8 minutes ago Up 7 minutes 0.0.0.0:3456->3456/tcp, 0.0.0.0:38080->80/tcp angry_hoover

Ports on the right(after ->) are exposed on the container

ports on left are exposed on the host

Run an instance of kodekloud/simple-webapp with a tag blue and map port 8080 on the container to 38282 on the host.

docker run -p 38282:8080 kodekloud/simple-webapp:blue

/volume mapping and persisting data/

  • docker run -v /opt/datadir:/var/lib/mysql mysql keep data outside docker

Bind mounts have been around since the early days of Docker. Bind mounts have limited functionality compared to volumes. When you use a bind mount, a file or directory on the /host machine/ is mounted into a container. The file or directory is referenced by its full or relative path on the host machine. By contrast, when you use a volume, a new directory is created within Docker’s storage directory on the host machine, and Docker manages that directory’s contents.

/environment variables/

  • docker run -e APP_COLOR=blue simple-webapp-color
  • docker inspect container-name under config - you find environment vans

Run a container named blue-app using image kodekloud/simple-webapp and set the environment variable APP_COLOR to blue. Make the application available on port 38282 on the host. The application listens on port 8080.

docker run --name blue-app -p 38282:8080 -e APP_COLOR=blue kodekloud/simple-webapp

Deploy a mysql database using the mysql image and name it mysql-db.

Set the database password to use db_pass123. Lookup the mysql image on Docker Hub and identify the correct environment variable to use for setting the root password.

docker run --name mysql-db -e MYSQL_ROOT_PASSWORD=db_pass123 mysql

docker inspect

  • docker inspect container-id or container-name

docker logs

  • `docker logs container-id or container-name

docker ps

  • docker ps list all running containers and basic info

  • docker ps -a list all running containers and non running containers

docker stop

  • docker stop container-id or container-name stop container

docker rm

  • docker rm container-id or container-name completely remove a container to save space

docker exec

  • docker exec container-name cat /etc/hosts See contents of file in container
  • docker exec -it <mycontainer> bash

docker attach

  • docker attach container-id or container-nameattach to container later

Images

docker images

  • docker images list of available images and sizes

docker rmi

  • docker rmi nginx remove image completely

docker pull

  • docker pull nginx pull the image store it and not run it

docker history

  • docker history apricot13/simple-webapp Show the history of an image

docker build

  • docker build .
  • if a step fails it starts from failed section

creating own images

Manual app setup:

  1. install os (ubuntu)
  2. update with apt get
  3. install dependencies using apt
  4. install python dependencies with pip
  5. copy source code to /opt folder
  6. run server using flask command

Create Dockerfile text file written in instruction and arguments format

every dockerfile is based off another image (either of an os or another image)

(in this instance source code is in folder were running from)

FROM Ubuntu

RUN apt-get update
RUN apt-get install python

RUN pip install flask
RUN pip install flask-mysql

COPY . /opt/source-code

ENTRYPOINT FLASK_APP=/opt/source-code/app.py flask run


docker build Dockerfile -t apricot13/my-custom-app create local image

docker push apricot13/my-custom-app push to dockerhub

Build a docker image using the Dockerfile and name it webapp-color. No tag to be specified.

docker build Dockerfile -t webapp-color docker build . -t webapp-color

Run an instance of the image webapp-color and publish port 8080 on the container to 8282 on the host.

docker run -p 8282:8080 webapp-color

What is the base Operating System used by the python:3.6 image?

Run docker run python:3.6 cat /etc/*release* command

Docker cmd's arguments and entrypoints

  • containers only live as long as the process inside them is running

  • who defines whcih process is run in each container? - dockerfile CMD command

  • bash is the defailt command for an os image - by default no terminal attached on run - terminal not found so container exists.

  • how to override default command? append command docker run ubuntu sleep 5

  • want image to always run sleep when it starts? create own image and specify new command

FROM Ubuntu
CMD sleep 4 or CMD ["command", "param1"] CMD ["sleep", "5"]
  • when you specifify in json format must be command then parameter

  • how to change the sleep value?

FROM Ubuntu

ENTRYPOINT ["sleep"]
  • docker run ubuntu-sleeper 10 ENTRYPOINT replaces CMD parameter is appended to ENTRYPOINT value if you dont enter 10 youre just running 'sleep command'

  • to create a default value:

FROM Ubuntu
ENTRYPOINT ["sleep"]
CMD ["5"]
  • command at startup sleep 5

  • docker run ubuntu-sleeper 10 command at start-up sleep 10

  • You can override entry points with docker run --entrypoint sleep2.0 ubuntu-sleeper 10 runs sleep2.0 10 on startup

Run an instance of the ubuntu image to run the sleep 1000 command at startup

Run it in detached mode.

docker run -d ubuntu sleep 1000

Docker networking

docker network

  • docker network ls
  • docker network inspect bridge

docker creates 3 networks when you install it

  • bridge - default network a container gets attached too
    • to access from outside map the ports (-p hostport:containerport)
  • none docker run Ubuntu --network=none
    • not attached to any network - no access to external network or other containers
  • Host docker run Ubuntu --network=host
    • web container uses the hosts network 0 no port mapping - cant run multiple web containers

to associate with any other host you use the --network parameter

  • all containers can resolve each others ips using the name of the container
    • mysql.connect(container-name)
    • 127.0.0.11 dns server always runs at
  • docker uses network namespaces - create separate namespace for each container

Run a container named alpine-2 using the alpine image and attach it to the none network.

docker run --name alpine-2 alpine --network=none

Create a new network named wp-mysql-network using the bridge driver. Allocate subnet 182.18.0.1/24. Configure Gateway 182.18.0.1

docker network create --driver bridge --subnet 182.18.0.1/24 --gateway 182.18.0.1 wp-mysql-network

Deploy a mysql database using the mysql:5.6 image and name it mysql-db. Attach it to the newly created network wp-mysql-network

Set the database password to use db_pass123. The environment variable to set is MYSQL_ROOT_PASSWORD

docker run -d --name mysql-db -e MYSQL_ROOT_PASSWORD=db_pass123 --network wp-mysql-network mysql:5.6

Deploy a web application named webapp, using image kodekloud/simple-webapp-mysql. Expose port to 38080 on the host. The application takes an environment variable DB_Host that has the hostname of the mysql database. Make sure to attach it to the newly created network wp-mysql-network

docker run --network=wp-mysql-network -e DB_Host=mysql-db -e DB_Password=db_pass123 -p 38080:8080 --name webapp --link mysql-db:mysql-db -d kodekloud/simple-webapp-mysql

data

  • /var/lib/docker

  • aufs

  • containers

  • image

  • volumes

image-2020062542129214

  • copy on write mechanism - to edit file in the read only layer when you write to the file a copy is taken and brought into the readwrtie container layer so the files in the image layer is not modified
  • when we delete container changes get deleted
  • how to Persist data persistent volume
  • docker volume create data_volume
    • var/lib/docker
      • volumes
        • data_volume
    • docker run -v data_volume:/var/lib/mysql mysql(docker will automatically create a volume if not created previously) (volume mounting)
  • docker run -v /data/mysql:/var/lib/mysql mysql if data already exists on the host (bind mounting) mound directory from any location on docker host
  • -v old style --mount preferred
  • docker run --mount type=bind,source=/data/mysql,target=/var/lib/mysql mysql
  • image-2020062542953243

docker uses storage drivers: AUFS, ZFS BTRFS Device mapper overlay overlay2 - docker chooses best automatically

Run a mysql container named mysql-db using the mysql image. Set database password to db_pass123

Note: Remember to run it in the detached mode.

docker run -e MYSQL_ROOT_PASSWORD=db_pass123 --name mysql-db -d mysql

docker exec mysql-db mysql -pdb_pass123 -e 'use foo; select * from myTable'

Run a mysql container again, but this time map a volume to the container so that the data stored by the container is stored at /opt/data on the host.

Use the same name : mysql-db and same password: db_pass123 as before. Mysql stores data at /var/lib/mysql inside the container.

docker run -e MYSQL_ROOT_PASSWORD=db_pass123 --name mysql-db --mount type=volume,source=/opt/data/,target=/var/lib/mysql -d mysql

or docker run -v /opt/data:/var/lib/mysql -d --name mysql-db -e MYSQL_ROOT_PASSWORD=db_pass123 mysql

docker compose

image-2020062544447828

docker-compose up

  • only applicable on single docker host

Single docker engine - voting application

docker run method

docker run -d --name=redis redis
docker run -d --name=db postgres:9.4
docker run -d --name=vote -p 5000:80 voting-app
docker run -d --name=result -p 5001:80
docker run -d --name=worker worker
  • problem: creates the containers but doesn't link them together
  • --link nameofcontainer:nameofhostapplookingfor creates entry into voting app container hosts file
  • --link deprecated docker swarm improves this.
docker run -d --name=redis redis
docker run -d --name=db postgres:9.4 --link db:db
docker run -d --name=vote -p 5000:80 --link redis:redis voting-app
docker run -d --name=result -p 5001:80
docker run -d --name=worker --link db:db --link redis:redis worker
def get_redis():
if not hasattr(g, 'redis'):
g.redis = Redis(host="redis", db=0, socket_timeout=5)
return g.redis

docker-compose method

  • NB db:db === db
redis:
image: redis
db:
image: postgres:9.4
vote:
image: voting-app
ports:
- 5000:80
links:
- redis
result:
image: result-app
ports:
- 5001:80
links:
- db
worker:
image: worker
links:
- redis
- db

docker-compose up

vote: 
build: ./vote
ports:
- 5000:80
links:
- redis
  • ./vote points to a GitHub repo containing a dockerfile

image-2020062545907952

versioning dockercompose files

version 1 stuck on 1 bridged network

for v2 and up specify the version in top of file

version: 2

automatically create new bridged network and attaches them all - so v2 you dont need to use links

specify startup order depends_on:

version: 3

support for docker swarm

image-2020062550423451

networks in docker compose

two networks - frontend and backend

version: 2
services:
redis:
image: redis
networks:
- back-end
db:
image: postgres:9.4
networks:
- back-end
vote:
image: voting-app
ports:
- 5000:80
links:
- redis
networks:
- front-end
- back-end
result:
image: result-app
ports:
- 5001:80
links:
- db
networks:
- front-end
- back-end
worker:
image: worker
links:
- redis
- db
networks:
- back-end
networks:
front-end:
back-end:

First create a postgress database container called db, image postgres, environmental variable POSTGRES_PASSWORD=mysecretpassword

if you are unsure, check the hints section for the exact commands.

docker run -d -e POSTGRES_PASSWORD=mysecretpassword --name db postgres

Next let's create a simple wordpress container called wordpress, image: wordpress, link it to the container db and expose it on host port 8085

if you are unsure, check the hints section for the exact commands.

docker run -d --name wordpress -p 8085:80 --link db:db wordpress

version: 2
services:
db:
image: postgres
environment:
- POSTGRES_PASSWORD=mysecretpassword
wordpress:
image: wordpress
links:
- db
ports:
- 8085:80

Docker registry

docker images are storred in the docker registry

docker login private-registry.io

docker run private-registry.io/apps/internal-app

run your own version of docker hub locally

docker run -d -p 5000:5000 --name registry registry:2

docker image tag my-image localhost:5000/my-image register local image

docker push localhost:5000/my-imagepushed to local registery

docker pull localhost:5000/my-image

docker pull 192.168.56.100:5000/my-image

docker engine

image-2020062554446459

Good docker links:

https://medium.com/better-programming/customize-your-mysql-database-in-docker-723ffd59d8fb

https://stackoverflow.com/questions/27409761/docker-multiple-dockerfiles-in-project