--- title: Developing with Docker author: gitlab.com/xlgmokha/developing-with-docker date: 2020-06-10 --- # Developing with Docker - Mo Khan | Software Engineer | Composition Analysis | GitLab ```text How to Docker better? ## . ## ## ## == ## ## ## ## ## === /"""""""""""""""""\___/ === { / ===- \______ O __/ \ \ __/ \____\_______/ ``` # Agenda * Definitions * Ecosystem * Build * Analyze * Optimize ```text < What are we going to talk about? > ---------------------------------- \ \ \ ## . ## ## ## == ## ## ## ## === /""""""""""""""""___/ === ~~~ {~~ ~~~~ ~~~ ~~~~ ~~ ~ / ===- ~~~ \______ o __/ \ \ __/ \____\______/ ``` # Definitions * Image * Container * Registry # Definitions - Image A Docker image is similar to a Ruby class. A class defines the behaviour and data associated with the class. ```ruby class Person def fist_bump(other_person) end end ``` # Definitions You can't do much with a class until you create an instance of one. ```ruby mo = Person.new you = Person.new ``` # Definitions - Objects Once a class is instantiated you can invoke methods on the object. An object can interact with other objects. ```ruby mo.first_bump(you) ``` # Definitions - Container A container is a running instance of an image. Similar to how an object is an instance of a class. | Ruby | Docker | | -- | -- | | Class | Image | | Object | Container | # Identifiers Classes can be identified by their name. Images can be identified by their image Id or `name:tag` Objects can be identified by their `object_id` in Ruby. Containers can be identified by their container Id or a name. | Ruby | Docker | | -- | -- | | Person | Image ID | | mo.object_id | Container ID | # Image identifier `[registry]name:tag` If the registry is omitted, then docker.io is assumed. * registry.gitlab.com/gitlab-org/security-products/license-management:latest * alpine:latest # Definitions - Registry Registry: stores images and makes them available to others This include metadata about images and blobs for each layer in the image. For example: * https://registry-1.docker.io * https://registry.gitlab.com ```bash curl -s -i https://registry-1.docker.io/v2/alpine/tags/list ``` # Architecture ```text ---------- | Client | ---------- | build | | pull | | run | ---------- | (tcp/unix socket) V --------------- | Docker Host | --------------- | Daemon | | Containers | | Images | -------------- | A V | ------------ | Registry | ------------ | Images | ------------ ``` https://docs.docker.com/get-started/overview/#docker-architecture # /var/run/docker.sock ```bash $ curl --unix-socket /var/run/docker.sock http://localhost/images/json ``` ```terminal32 curl -i --unix-socket /var/run/docker.sock http://localhost/images/json ``` # $ docker version The docker CLI is an HTTP client that can connect to Unix or TCP sockets. ```terminal32 docker version ``` # $ docker image ls ```terminal32 docker image ls --format "table {{.ID}}\t{{.Repository}}\t{{.Tag}}\t{{.Size}}" ``` # $ docker ps ```terminal32 docker ps --format "table {{.ID}}\t{{.Image}}\t{{.Status}}" ``` # $ docker run -it alpine:latest cat /etc/os-release 1. check if "alpine:latest" is on docker host 1. download "alpine:latest" from registry to docker host 1. start a container using the "alpine:latest" image ```terminal32 docker run -it alpine:latest cat /etc/os-release ``` # Dockerfile ```file path: examples/001/Dockerfile relative: true lang: docker ``` https://docs.docker.com/engine/reference/builder/ # FROM alpine:latest Initializes a build stage and sets a Base Image. ```file path: examples/001/Dockerfile relative: true lang: docker ``` # COPY "hello.rb" Copy "hello.rb" from the host to "/usr/local/bin/hello" within the Docker image. ```file path: examples/001/Dockerfile relative: true lang: docker ``` ```bash $ cat examples/001/hello.rb ``` ```file path: examples/001/hello.rb relative: true lang: ruby ``` # Dockerfile - RUN RUN a command from within the image and make "hello" executable. ```file path: examples/001/Dockerfile relative: true lang: docker lines: start: 2 end: 3 ``` # Dockerfile - CMD Set the default command to run when the docker image is launched as a container. ```file path: examples/001/Dockerfile relative: true lang: docker lines: start: 3 end: 4 ``` # docker build -t developing-with-docker:latest examples/001/ ```terminal32 time docker build -t developing-with-docker:latest examples/001/ ``` # docker run developing-with-docker:latest ```terminal32 docker run developing-with-docker:latest ``` # docker run -it developing-with-docker:latest /bin/sh ```terminal32 docker run -it developing-with-docker:latest /bin/sh ``` # docker ps ```terminal32 docker ps --format "table {{.ID}}\t{{.Image}}\t{{.Status}}" ``` # docker exec -it /bin/sh ```terminal32 bash -i examples/001/docker-exec.sh ``` # dive Useful for identifying bloat. https://github.com/wagoodman/dive * Displays each layer * Allows investigating files that are added/removed/changed in each layer ```terminal32 bash examples/001/dive-exec.sh developing-with-docker ``` # docker pull registry.gitlab.com/gitlab-org/security-products/license-management:latest * More layers == more parallel downloads * Smaller layers == faster downloads per layer ```terminal32 bash -i examples/001/docker-large-download.sh ``` # docker build -t big-image:latest examples/002/ ```file path: examples/002/Dockerfile relative: true lang: docker ``` ```terminal32 time docker build -t big-image:latest examples/002/ ``` # docker image ls ```terminal32 docker image ls --format "table {{.ID}}\t{{.Repository}}\t{{.Tag}}\t{{.Size}}" ``` # dive big-image:latest ```terminal32 bash examples/001/dive-exec.sh big-image ``` # docker build -t small-image:latest examples/003/ * Collapse layers * Cleanup unnecessary artifacts * Deflate files within layers * Inflate files when container is launched ```file path: examples/003/Dockerfile relative: true lang: docker ``` ```file path: examples/003/run.sh relative: true lang: sh ``` ```terminal32 time docker build -t small-image:latest examples/003/ ``` # docker image ls ```terminal32 docker image ls --format "table {{.ID}}\t{{.Repository}}\t{{.Tag}}\t{{.Size}}" ``` # dive small-image:latest ```terminal32 bash examples/001/dive-exec.sh small-image ``` # docker run -it small-image:latest ```terminal32 docker run -it small-image:latest ``` # docker image ls ```terminal32 docker image ls --format "table {{.ID}}\t{{.Repository}}\t{{.Tag}}\t{{.Size}}" ``` # Summary * Keep each layer small * More layers provides opportunity for more parallel downloads # Fin Thank you for your time [gitlab.com/xlgmokha/developing-with-docker](https://gitlab.com/xlgmokha/developing-with-docker)