diff --git a/docker.html.markdown b/docker.html.markdown index 1df49cc3..e18db5c9 100644 --- a/docker.html.markdown +++ b/docker.html.markdown @@ -5,144 +5,277 @@ filename: docker.bat contributors: - ["Ruslan López", "http://javapro.org/"] - ["Michael Chen", "https://github.com/ML-Chen"] + - ["Akshita Dixit", "https://github.com/akshitadixit"] + - ["Marcel Ribeiro-Dantas", "https://github.com/mribeirodantas"] --- -```bat -:: download, install and run hello-world image -docker run hello-world +Docker is a tool that helps you build, test, ship and run applications +seamlessly across various machines. It replicates the environment our software +needs on any machine. You can get Docker for your machine from +https://docs.docker.com/get-docker/ -:: if this is the first time you should be able to see the message -:: Unable to find image 'hello-world:latest' locally -:: latest: Pulling from library/hello-world -:: 1b930d010525: Pull complete -:: Digest: sha256:4fe721ccc2e8dc7362278a29dc660d833570ec2682f4e4194f4ee23e415e1064 -:: 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. -:: (amd64) -:: 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://hub.docker.com/ -:: -:: For more examples and ideas, visit: -:: https://docs.docker.com/get-started/ +It has grown in popularity over the last decade due to being lightweight and +fast as compared to virtual-machines that are bulky and slow. Unlike VMs, docker +does not need a full blown OS of its own to be loaded to start and does not +compete for resources other than what the application it is running will use. +VMs on the other hand are pretty resource intensive on our processors, disks and +memory hence running multiple VMs for various applications becomes a challenge +in a limited capacity architecture. -:: now let's see currently running images -docker ps -:: CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS -:: NAMES +
+┌────────────────────────┐ ┌───────────────────────┐
+│      ┌───────────┐     │ │      ┌───────────┐    │
+│      │   App     │     │ │      │   App     │    │
+│      └───────────┘     │ │      └───────────┘    │
+│  ┌────────┐ ┌────────┐ │ │  ┌────────┐ ┌───────┐ │
+│  │  Libs  │ │  Deps  │ │ │  │  Libs  │ │  Deps │ │
+│  └────────┘ └────────┘ │ │  └────────┘ └───────┘ │
+│  ┌───────────────────┐ │ │  ┌──────────────────┐ │
+│  │      Guest OS     │ │ │  │     Guest OS     │ │
+│  └───────────────────┘ │ │  └──────────────────┘ │
+│           VM1          │ │           VM2         │
+└────────────────────────┘ └───────────────────────┘
+┌──────────────────────────────────────────────────┐
+│                     Hypervisor                   │
+└──────────────────────────────────────────────────┘
+┌──────────────────────────────────────────────────┐
+│                      Host OS                     │
+└──────────────────────────────────────────────────┘
+┌──────────────────────────────────────────────────┐
+│             Hardware Infrastructure              │
+└──────────────────────────────────────────────────┘
+              (VM based architecture)
 
-:: let's see the images we have ran previously
-docker ps -a
+┌────────────────────────┐ ┌───────────────────────┐
+│      ┌───────────┐     │ │      ┌───────────┐    │
+│      │   App     │     │ │      │   App     │    │
+│      └───────────┘     │ │      └───────────┘    │
+│  ┌────────┐ ┌────────┐ │ │  ┌────────┐ ┌───────┐ │
+│  │  Libs  │ │  Deps  │ │ │  │  Libs  │ │  Deps │ │
+│  └────────┘ └────────┘ │ │  └────────┘ └───────┘ │
+│        Container1      │ │       Container2      │
+└────────────────────────┘ └───────────────────────┘
+┌──────────────────────────────────────────────────┐
+│                       Docker                     │
+└──────────────────────────────────────────────────┘
+┌──────────────────────────────────────────────────┐
+│                        OS                        │
+└──────────────────────────────────────────────────┘
+┌──────────────────────────────────────────────────┐
+│             Hardware Infrastructure              │
+└──────────────────────────────────────────────────┘
+            (Docker based architecture)
 
-:: CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS                     PORTS     
-::          NAMES
-:: 4a76281f9c53        hello-world         "/hello"            2 minutes ago       Exited (0) 2 minutes ago             
-::          happy_poincare
-:: the name part is generated automatically so it probably will be different for you
+
-:: let's remove our previously generated image -docker rm happy_poincare +Couple of terms we will encounter frequently are Docker Images and Docker +Containers. Images are packages or templates of containers all stored in a +container registry such as [Docker Hub](https://hub.docker.com/). Containers +are standalone, executable instances of these images which include code, +runtime, system tools, system libraries and settings - everything required to +get the software up and running. Coming to Docker, it follows a client-server +architecture wherein the CLI client communicates with the server component, +which here is, the Docker Engine using RESTful API to issue commands. -:: let's test if it was really deleted -docker ps -a -:: CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS -:: NAMES +## The Docker CLI +```bash +# after installing Docker from https://docs.docker.com/get-docker/ +# To list available commands, either run `docker` with no parameters or execute +# `docker help` +$ docker -:: specify a custom name for the container -docker run --name test_container hello-world -:: 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. -:: (amd64) -:: 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://hub.docker.com/ -:: -:: For more examples and ideas, visit: -:: https://docs.docker.com/get-started/ +>>> docker [OPTIONS] COMMAND [ARG...] + docker [ --help | -v | --version ] -docker ps -a -:: CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS -:: NAMES -:: d345fe1a4f41 hello-world "/hello" About a minute ago Exited (0) About a minute ago -:: test_container -:: as you can see the name is now what we have specified + A self-sufficient runtime for containers. -:: retrieve logs from a named container -docker logs test_container -:: 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. -:: (amd64) -:: 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://hub.docker.com/ -:: -:: For more examples and ideas, visit: -:: https://docs.docker.com/get-started/ + Options: + --config string Location of client config files (default "/root/.docker") + -c, --context string Name of the context to use to connect to the daemon (overrides DOCKER_HOST env var and default context set with "docker context use") + -D, --debug Enable debug mode + --help Print usage + -H, --host value Daemon socket(s) to connect to (default []) + -l, --log-level string Set the logging level ("debug"|"info"|"warn"|"error"|"fatal") (default "info") + --tls Use TLS; implied by --tlsverify + --tlscacert string Trust certs signed only by this CA (default "/root/.docker/ca.pem") + --tlscert string Path to TLS certificate file (default "/root/.docker/cert.pem") + --tlskey string Path to TLS key file (default "/root/.docker/key.pem") + --tlsverify Use TLS and verify the remote + -v, --version Print version information and quit -docker rm test_container + Commands: + attach Attach to a running container + # […] -docker run ubuntu -:: Unable to find image 'ubuntu:latest' locally -:: latest: Pulling from library/ubuntu -:: 2746a4a261c9: Pull complete -:: 4c1d20cdee96: Pull complete 0d3160e1d0de: Pull complete c8e37668deea: Pull complete Digest: sha256:250cc6f3f3ffc5cdaa9d8f4946ac79821aafb4d3afc93928f0de9336eba21aa4 -:: Status: Downloaded newer image for ubuntu:latest +$ docker run hello-world +# `docker run ` is used to run a container, it will pull the +# images from Docker Hub if they don't already exist in your system. Here the +# docker client connects to the daemon which in turn pulls the "hello-world" +# image from the Docker Hub. The daemon then builds a new container from the +# image which runs the executable that produces the output streamed back to the +# client that we see on our terminals. -docker ps -a -:: CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS -:: NAMES -:: c19e9e5b000a ubuntu "/bin/bash" 5 seconds ago Exited (0) 4 seconds ago -:: relaxed_nobel +$ docker run -d ubuntu sleep 60s +# The -d (or --detach) flag is when we want to run a container in the background +# and return back to the terminal. Here we detach an ubuntu container from the +# terminal, the output should be the id and the command exits. If we check +# running containers, we should still see ours there: +# CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES +# 133261b4894a ubuntu "sleep 60s" 3 seconds ago Up 2 seconds vigorous_gould -:: running a container in an interactive mode -docker run -it ubuntu -:: root@e2cac48323d2:/# uname -:: Linux -:: root@e2cac48323d2:/# exit -:: exit +$ docker run -p 3000:8000 +# The -p (or --publish) flag is used to expose port 8000 inside the container to +# port 3000 outside the container. This is because the app inside the container +# runs in isolation, hence the port 8000 where the app runs is private to the +# container. -docker rm relaxed_nobel +$ docker run -i +# or +$ docker run -it +# Docker runs our containers in a non-interactive mode i.e. they do not accept +# inputs or work dynamically while running. The -i flag keeps input open to the +# container, and the -t flag creates a pseudo-terminal that the shell can attach +# to (can be combined as -it) -docker ps -a -:: CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS -:: NAMES -:: e2cac48323d2 ubuntu "/bin/bash" 2 minutes ago Exited (0) About a minute ago -:: nifty_goldwasser +$ docker ps -a +# The `docker ps` command only shows running containers by default. To see all +# containers, use the -a (or --all) flag +# Running the above command should output something similar in the terminal: +# CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES +# 82f84bf6912b hello-world "/hello" 9 minutes ago Exited (0) 9 minutes ago eloquent_sammet + + +$ docker stop hello-world +# or +$ docker start hello-world +# The stop command simply stops one or more containers, and the start command +# starts the container(s) up again! `docker start -a ubuntu` will attach our +# detached container back to the terminal i.e. runs in the foreground + +$ docker create alpine +# `docker create` creates a new container for us with the image specified (here, +# alpine), the container does not auto-start unlike `docker run`. This command +# is used to set up a container configuration and then `docker start` to shoot +# it up when required. Note that the status is "Created": +# CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES +# 4c71c727c73d alpine "/bin/sh" 29 seconds ago Created naughty_ritchie + +$ docker rm 82f84 +# Removes one or more containers using their container ID. +# P.S.: we can use only the first few characters of the entire ID to identify +# containers + +$ docker images +# Displays all images and their information, created here means the latest image +# tag updated on Docker Hub: +# REPOSITORY TAG IMAGE ID CREATED SIZE +# ubuntu latest a8780b506fa4 9 days ago 77.8MB +# alpine latest 9c6f07244728 3 months ago 5.54MB +# hello-world latest feb5d9fea6a5 13 months ago 13.3kB + +$ docker rmi +# Removes one or more images from your system which do not have their instances +# (or containers as we know them) running. If the image has an attached +# container, either delete the container first or use the -f (or --force) flag +# to forcefully delete both the container and image. + +$ docker pull busybox +# The pull command downloads the specified image on our system from Docker Hub. + +$ docker exec -it 7b272 bash +# This command is used to run a command in the running container's default +# directory. Here 7b272 was our ubuntu container and the above command would +# help us interact with the container by opening a bash session. + +$docker logs +# Displays the information logged by the specified container +# root@7b27222e4bb7:/# whoami +# root +# root@7b27222e4bb7:/# pwd +# / +# root@7b27222e4bb7:/# ls +# bin boot dev etc home lib lib32 lib64 libx3 srv sys tmp usr var +# root@7b27222e4bb7:/# exit +# exit + +# More commands can be found at https://docs.docker.com/engine/reference/commandline/docker/ +``` +## The Dockerfile +The Dockerfile is a blueprint of a Docker image. We can mention the artifacts +from our application along with their configurations into this file in the +specific syntax to let anyone create a Docker image of our application. + +### A few things to keep in mind: +* It is always strictly named `Dockerfile` without any extensions +* We have to build our custom image on top of some already available Docker base +image. (there is an empty image called `scratch` which literally lets you build +an image from scratch) +* All capitalised commands are part of the syntax, they are not case-sensitive +but used like a convention +* Below is a sample Dockerfile but you can read in depth from the [official docs](https://docs.docker.com/engine/reference/builder/). + +```Dockerfile +FROM +# define base image + +ENV USERNAME='admin'\ + PWD='****' +# optionally define environmental variables + +RUN apt-get update +# run linux commands inside container env, does not affect host env +# This executes during the time of image creation + +COPY +# executes on the host, copies files from src (usually on the host) to target +# on the container + +ENTRYPOINT ["some-script.sh"] +# executes an entire script as an entrypoint + +CMD [,...] +# always part of dockerfile, introduces entry point linux command e.g. +# `CMD node server.js` +# This executes after image creation only when the container from the image +# is running. +``` +### Build your images +Use the `docker build` command after wrapping your application into a Docker +image to run ( or build) it. + +```bash + +$docker build +# used to build an image from the specified Dockerfile +# instead of path we could also specify a URL +# -t tag is optional and used to name and tag your images for e.g. +# `$docker build -t my-image:0.1 ./home/app` +# rebuild images everytime you make changes in the dockerfile +``` + +## Push your image to DockerHub +If you want your application's Docker image to be made publically available for +any Docker user, you might wanna push it to the [Docker Hub](https://hub.docker.com/) which is a +registry of Docker images. Make sure you have an account with a username and +password on Docker Hub. + +When pushing an image to Docker Hub, we must specify our Docker Hub username +as part of the source image name. We need to create the target image with the +tag name of username/image-name much like GitHub repositories. + +```bash +$docker login +# to login to Docker Hub using your username and password + +$docker tag [:] [:] +# this tags a local src-image to a public target-image +# e.g. `docker tag my-sample-app:1.0.0 akshitadixit/my-sample-app` +# if tags are not specified, they're defaulted to `latest` + +$docker push [:] +# uploads our image to Docker Hub +# e.g. `docker push akshitadixit/my-sample-app` +# this image will be accessible under your profile's repositories as +# `https://hub.docker.com/r/username/image-name` -docker rm nifty_goldwasser ```