Skip to main content

Docker

11th October, 2022

Updated: 12th October, 2022

    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

    docker port mapping 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

    docker data 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
    • docker volumes 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

    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

    dckercomposebuild 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

    docker versions 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

    dockerengine 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


    b18e6248-61d5-476b-a7cf-f9e3d717826e

    Created on: 11th October, 2022

    Last updated: 12th October, 2022

    Tagged With: