# Docker ###### tags: `Container` `Docker` `Author:John Chen` --- [TOC] ## Docker overview Docker is an open platform for **developing, shipping, and running applications**. Docker enables you to **separate your applications from your infrastructure** so you can **deliver software quickly**. With Docker, you can manage your infrastructure in the same ways you manage your applications. By taking advantage of **Docker’s methodologies for shipping, testing, and deploying code quickly**, you can significantly reduce the delay between writing code and running it in production. ### [Cloud Structure] ![](https://i.imgur.com/BQ3oc5w.png) ### The Docker platform Docker provides the ability to package and run an application in a loosely isolated environment called a **container**. The isolation and security allow you to run many containers **simultaneously** on a given host. Containers are lightweight because they ==don’t need the extra load of a hypervisor, but run directly within the host machine’s kernel==. This means you can run more containers on a given hardware combination than if you were using virtual machines. You can even run Docker containers within host machines that are actually virtual machines! ### [VM v.s. Container] ![](https://i.imgur.com/xCjTqqg.png) ![](https://i.imgur.com/dnJU34N.png) ![](https://i.imgur.com/LnWsn5H.png) ![](https://i.imgur.com/tJShLP0.png) ==Docker can use different interfaces to access virtualization features of the Linux kernel.== ![](https://i.imgur.com/GJlWCO9.png) #### Docker使用的Linux核心模組功能包括下列各項: * [**Namespace**](https://en.wikipedia.org/wiki/Linux_namespaces) – 用來隔離不同Container的執行空間,像是把Process ID、User ID、Network…等等的環境執行狀態隔離開來。舉個例子來說在一台實體機器上,有 2個 Namespace,Namespace 1 和 Namepsace2。Namespace 1 裡面的 PID 有 1,Namespace 2的PID 也可以有 1 的 PID,這樣就做到執行環境上PID 的隔離。 ![](https://i.imgur.com/KniLb4N.png) * [**Cgroup**](https://en.wikipedia.org/wiki/Cgroups) – 用來分配硬體資源 `有了 Namespace 和 Cgroup 後,就可以做到在同一個 Kernel的系統環境下,有效的隔離資源的使用。` * [**AUFS(chroot)**](https://zh.wikipedia.org/wiki/Aufs) – 用來建立不同Container的檔案系統 * SELinux – 用來確保Container的網路的安全 * Netlink – 用來讓不同Container之間的行程進行溝通 * Netfilter – 建立Container埠為基礎的網路防火牆封包過濾 * AppArmor – 保護Container的網路及執行安全 * Linux Bridge – 讓不同Container或不同主機上的Container能溝通 #### 補充中文說明: * [**何謂Container**](https://www.ithome.com.tw/news/91839) * [**Docker Q&A**](https://www.ithome.com.tw/news/91847) ![](https://i.imgur.com/6q3rvAO.png) --- ### Docker Engine Docker Engine is a **client-server** application with these major components: * A **server** which is a type of long-running program called a daemon process (the ==dockerd== command). * A **REST API** which specifies interfaces that programs can use to talk to the daemon and instruct it what to do. * A **command line interface (CLI)** client (the ==docker== command). ![](https://i.imgur.com/D8PSki6.png) ==The CLI uses the Docker REST API to control or interact with the Docker daemon through scripting or direct CLI commands. Many other Docker applications use the underlying API and CLI.== ==The daemon creates and manages Docker objects, such as **images**, **containers**, **networks**, and **volumes**.== > Note: Docker is licensed under the open source Apache 2.0 license. ### What can I use Docker for? Fast, consistent delivery of your applications Docker streamlines the development lifecycle by allowing developers to work in standardized environments using local containers which provide your applications and services. ==Containers are great for continuous integration and continuous delivery (CI/CD) workflows==. Consider the following example scenario: * Your developers write code locally and share their work with their colleagues using Docker containers. They **use Docker to push their applications into a test environment and execute automated and manual tests**. * When developers find bugs, they **can fix them in the development environment and redeploy them to the test environment for testing and validation**. * When testing is complete, getting the fix to the customer is as simple as pushing the updated **image** to the production environment. #### Responsive deployment and scaling Docker’s ==container-based== platform allows for **highly portable workloads**. Docker containers can run on a developer’s local laptop, **on physical or virtual machines in a data center, on cloud providers, or in a mixture of environments**. Docker’s portability and lightweight nature also make it easy to dynamically manage workloads, **scaling up or tearing down** applications and services as business needs dictate, in near real time. #### Running more workloads on the same hardware Docker is lightweight and fast. It provides a viable, cost-effective alternative to hypervisor-based virtual machines, so you can use more of your compute capacity to achieve your business goals. Docker is perfect for high density environments and for small and medium deployments where you need to do more with fewer resources. ### Docker architecture Docker uses a **client-server** architecture. The Docker client talks to the **Docker daemon**, which **does the heavy lifting of building, running, and distributing your Docker containers**. The Docker client and daemon can run on the same system, or you can connect a Docker client to a remote Docker daemon. The Docker client and daemon communicate using a **REST API, over UNIX sockets or a network interface**. ![](https://i.imgur.com/UPqG8Mo.png) #### **The Docker daemon** The Docker daemon (==dockerd==) **listens for Docker API requests and manages Docker objects** such as **images, containers, networks, and volumes**. A daemon can also communicate with other daemons to manage Docker services. #### **The Docker client** The Docker client (==docker==) is the primary way that many Docker users interact with Docker. When you use commands such as *docker run*, the client sends these commands to dockerd, which carries them out. The docker command uses the Docker API. The Docker client can communicate with more than one daemon. #### **Docker registries** A Docker registry stores Docker images. **Docker Hub and Docker Cloud are public registries** that anyone can use, and **Docker is configured to look for images on Docker Hub by default**. You can even run your own private registry. If you use **Docker Datacenter (DDC), it includes Docker Trusted Registry (DTR)**. When you use the docker pull or docker run commands, the required images are pulled from your configured registry. When you use the docker push command, your image is pushed to your configured registry. Docker store allows you to buy and sell Docker images or distribute them for free. For instance, you can buy a Docker image containing an application or service from a software vendor and use the image to deploy the application into your testing, staging, and production environments. You can upgrade the application by pulling the new version of the image and redeploying the containers. #### **Docker objects** When you use Docker, you are creating and using images, containers, networks, volumes, plugins, and other objects. This section is a brief overview of some of those objects. ##### *IMAGES* An **image is a read-only template** with instructions for **creating a Docker container**. Often, an image is based on another image, with some additional customization. For example, you may build an image which is based on the ubuntu image, but installs the Apache web server and your application, as well as the configuration details needed to make your application run. You might create your own images or you might only use those created by others and published in a registry. To build your own image, you create a Dockerfile with a simple syntax for defining the steps needed to create the image and run it. **Each instruction in a Dockerfile creates a layer in the image**. When you change the Dockerfile and rebuild the image, only those layers which have changed are rebuilt. This is part of what makes images so lightweight, small, and fast, when compared to other virtualization technologies. ##### *CONTAINERS* A container is a runnable instance of an image. **You can create, start, stop, move, or delete a container using the Docker API or CLI. You can connect a container to one or more networks, attach storage to it, or even create a new image based on its current state**. By default, a container is relatively well isolated from other containers and its host machine. You can control how isolated a container’s network, storage, or other underlying subsystems are from other containers or from the host machine. A container is defined by its image as well as any configuration options you provide to it when you create or start it. When a container is removed, any changes to its state that are not stored in persistent storage disappear. --- **Example `docker run` command** The following command runs an `ubuntu` container, attaches interactively to your local command-line session, and runs `/bin/bash`. ```shell=1 $ docker run -i -t ubuntu /bin/bash ``` When you run this command, the following happens (assuming you are using the default registry configuration): 1. If you do not have the **`ubuntu`** image locally, Docker pulls it from your configured registry, as though you had run **`docker pull ubuntu`** manually. 2. Docker creates a new container, as though you had run a **`docker container create`** command manually. 3. Docker allocates a read-write filesystem to the container, as its final layer. This allows a running container to create or modify files and directories in its local filesystem. 4. Docker creates a network interface to connect the container to the default network, since you did not specify any networking options. This includes assigning an IP address to the container. By default, containers can connect to external networks using the host machine’s network connection. 5. Docker starts the container and executes **`/bin/bash`**. Because the container is running interactively and attached to your terminal (due to the **`-i`** and **`-t`** flags), you can provide input using your keyboard while the output is logged to your terminal. 6. When you type **`exit`** to terminate the **`/bin/bash`** command, the container stops but is not removed. You can start it again or remove it. ##### *SERVICES* **Services allow you to scale containers across multiple Docker daemons, which all work together as a swarm with multiple managers and workers. Each member of a swarm is a Docker daemon, and the daemons all communicate using the Docker API. A service allows you to define the desired state, such as the number of replicas of the service that must be available at any given time. By default, the service is load-balanced across all worker nodes**. To the consumer, the Docker service appears to be a single application. Docker Engine supports swarm mode in Docker 1.12 and higher. ## Docker concepts :::info #### Docker is a platform for developers and sysadmins to develop, deploy, and run applications with containers. The use of Linux containers to deploy applications is called containerization. Containers are not new, but their use for easily deploying applications is. ::: --- ## Containers and virtual machines :::info #### A container runs natively on Linux and shares the kernel of the host machine with other containers. It runs a discrete process, taking no more memory than any other executable, making it lightweight. #### By contrast, a virtual machine (VM) runs a full-blown “guest” operating system with virtual access to host resources through a hypervisor. In general, VMs provide an environment with more resources than most applications need. ::: ## WHAT IS A CONTAINER PLATFORM? A container platform is a complete solution that allows organizations to solve multiple problems across a diverse set of requirements. It is more than a piece of technology and orchestration - it delivers sustainable benefits throughout your organization by providing all the pieces an enterprise operation requires including security, governance, automation, support and certification over the entire application lifecycle. Docker Enterprise Edition (EE) is an enterprise-ready container platform that enables IT leaders to choose how to cost-effectively build and manage their entire application portfolio at their own pace, without fear of architecture and infrastructure lock-in. ![](https://i.imgur.com/rntiGRh.png) --- ![](https://i.imgur.com/zd9nTgW.png) --- ### [**Before Install**](https://www.ithome.com.tw/news/91848) ![](https://i.imgur.com/Bp3Az47.png) ![image](https://hackmd.io/_uploads/rkfLXQegbx.png) --- ## Intall Docker (Ubuntu 16.04, 18.04, 20.04) ### **1.** Uninstall Old Version Older versions of Docker were called docker, docker.io , or docker-engine. If these are installed, uninstall them: ```bash= $ sudo apt-get remove docker docker-engine docker.io containerd runc ``` ### **2.** Install Docker CE(Docker Community Edition) * **Install using the repository** Before you install Docker CE for the first time on a new host machine, you need to set up the Docker repository. Afterward, you can install and update Docker from the repository. * **SET UP THE REPOSITORY** 1. **`Update the apt package index:`** ```bash= $ sudo apt-get update ``` 2. **`Install packages to allow apt to use a repository over HTTPS:`** ```bash= $ sudo apt-get install \ apt-transport-https \ ca-certificates \ curl \ gnupg \ lsb-release ``` 3. **`Add Docker’s official GPG key:`** ```bash= $ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg ``` 4. **`Check the GPG key `** ```bash= $ apt-key list ``` You will see the following information. ![](https://i.imgur.com/VOm3mG9.png) 5. **`Use the following command to set up the stable repository.`** ``` $ echo \ "deb [arch=amd64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu \ $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null" ``` * **Install Docker CE** 1. **`Update the apt package index.`** ```bash= $ sudo apt-get update ``` 2. **`Install the latest version of Docker CE and containerd, or go to the next step to install a specific version:`** ``` $ sudo apt-get install docker-ce docker-ce-cli containerd.io ``` 3. **Configure Docker to start on boot** ``` $ sudo systemctl enable docker $ sudo systemctl start docker $ sudo service docker start ``` 4. **Set User** ``` $ sudo groupadd docker $ sudo usermod $(whoami) -G docker -a ``` ==Re-login your account to enable user== 5. **Test Docker CE** * **`Check Docker Version`** ```bash= $ docker version ``` ![](https://i.imgur.com/cOZrc6c.png) :::success **Docker installing successful** ::: --- ## Basic Commands 基本指令運用 ### Search httpd/nginx server by Docker #### 1. Search image (找尋docker image) :::info docker search <software name> ::: ``` # Search the httpd/nginx images $ docker search "apache http" $ docker search nginx ``` After searching, ![](https://i.imgur.com/zI68aAH.png) ![](https://i.imgur.com/7UnJA0T.png) **The more stars an image has the more popular and stable is.** #### 2.Pull **Image** (拉載image) :::info $ docker pull <docker image name> ::: ::: ```bash= # Search the http/nginx images $ docker pull httpd $ docker pull nginx ``` You will see these, ![](https://i.imgur.com/TjB3lrZ.png) ![](https://i.imgur.com/ff0WxLe.png) #### 3.List **Image** (查看現有image) ![](https://i.imgur.com/wzWEwdK.png) :::info $ docker images ::: ==*Images Locations:*== * `/var/lib/docker/{driver-name}` will contain the driver specific storage for contents of the images. * `/var/lib/docker/graph/<id>` now only contains metadata about the image, in the json and layersize files. In the case of aufs: * `/var/lib/docker/aufs/diff/<id>` has the file contents of the images. * `/var/lib/docker/repositories-aufs` is a JSON file containing local image information. This can be viewed with the command docker images. :::info You can change the images location by a **.json** file. 1. Create and edit the "daemon.json" ```shell= sudo vim /etc/docker/daemon.json ``` 2. Add the following content to the file, **==graph==** is the path location for execution and storage ```json= { "graph": "/mnt/your-docker-data", "storage-driver": "overlay" } ``` ::: #### 4. Run Docker **Container** :::info $ docker run --name <container name> -p <host port nimber>:<container port number> -v <host volumn>:<container internal volumn> -d <image respository:tag> ::: ```bash= # Run Docker image as a container # -d: Run container in background and print container ID. (表示container在背景執行) # -t: Allocate a pseudo-TTY (代表可以有文字輸出) # -i: Keep STDIN open even if not attached. (可以由STDIN輸入文字) # -v: Bind mount a volume. (綁定本地儲存volume與Docker container的儲存路徑) # -p: Publish a container's port(s) to the host. (將Host的port與container的port做映射) # --rm: Stop and remove container(process) after exiting from container # --restart: --restary=always => always start container after booting or exiting # --name: container's name $ docker run --name nginx_server -d -p 8080:80 -v /var/www:/var/shared/nginx/html nginx:latest # This command means to load the image whose name is "nginx" and tag is # "latest" (latest version), and turn it into a container (process) where the # host's port 8080 will be mapped to the container's port 80, and the local # directory will be mapped to /var/shared/nginx/html in this container. # This container (Nginx server) will be executed in the background. ``` ==Open a browser page on host, and type`https://127.0.0.1:8080`. If you can see follwing page, it means the Nginx container is running.== ![](https://i.imgur.com/O6Yrtpe.png) #### 5. List cotainer processes. :::info $ docker ps -a $ docker container ls -a ::: ```bash= #List the running containers $ docker ps #or $ docker container ls #List the hibernated containers $ docker ps -a ``` * Container is running ![](https://i.imgur.com/ny0fTDi.png) * Container is under hibernation ![](https://i.imgur.com/5jXVKcX.png) :::warning Try to run a new container which is named "nginx_server2" from the same image but it has a different network port mapping. 如果再從同樣的image去做出另一個container,這次只改變container名稱與network port的映射位置,會如何? ::: ```bash= $ docker run --name nginx_server -d -p 8888:80 -v /var/www:/var/shared/nginx/html nginx:latest ``` * A new container is created ![](https://i.imgur.com/SnNttw3.png) ==Open a browser on host, and type`https://127.0.0.1:8888`. If you cae see follwing page, the new container runs well.== ![](https://i.imgur.com/sOXCxqk.png) #### 5. How to start, stop, restart and delete a container。 :::info /# Start a container which is stopped. $ docker start <Container ID / Container Name> /# Stop a container which is started. $ docker stop <Container ID / Container Name> /# Stop a container, and then start it. $ docker restart <Container ID / Container Name> /# Remove a stopped container from ps list. $ docekr rm <Container ID / Container Name> /# Remove a container no matter what states is. $ docekr kill <Container ID / Container Name> ::: ```shell= # Note: For Docker Image, "stopping" the running container does not affect it in any way. $ docker stop [Name or ID] or docker kill [Name or ID] # Hibernated container can only be found by "docker ps -a" $ docker stop nginx_server2 (Wait for the process to exit on its own) # or $ docker kill 5f50459bc710 (Wait for the process to die, in last resort, try to kill the process directly) # Stopped container can be waked any time by "docker restart", "docker run" and a bunch of arguments $ docker restart nginx_server2 # To delete a container, you can use the "docker rm" command. If you want to run the container from the same image next time, you need to use the "docker run" command. $ docker rm nginx_server2 ``` #### 4. Get into the container console. ![](https://i.imgur.com/gorKHvN.png) ```bash= # Container還沒掛載執行前 $ docker run -it --name=gitea -p 10022:22 -p 10080:3000 -v /var/lib/gitea:/data gitea/gitea:latest /bin/bash # Container 使用 docker rnu -d在背景執行時: # docker exec -it [container 名稱 或是 ID] $ docker exec -it gitea_sw2 /bin/bash # or $ docker exec -ti 07a933b /bin/bash ``` 進入contanier console後的畫面如下 ![](https://i.imgur.com/N1ThIKA.png) ==輸入exit可跳出container console== #### 6. Container存成image與刪除image。 ![](https://i.imgur.com/NrsOCkM.png) ```bash= # 用 docker diff [名稱/ID]來查改修改過的內容 $ docker diff gitea_sw2 # or $ docker diff 07a933b ``` 顯示container修改過的檔案 ![](https://i.imgur.com/DRWrbDl.png) 輸入 docker images查看目前映像檔 ![](https://i.imgur.com/q4Bt6L0.png) ```bash= # 使用 docker commit [container名稱/ID] [iamge名稱]:[image Tag] (其中名稱可以跟現存的Image相同,但是Tag不可以一樣。) $ docker commit gitea_sw2 gitea:Aewin_sw2_V02 ``` commit後的結果如下: ![](https://i.imgur.com/iIe3pn5.png) ```bash= # 使用 docker rmi [container ID] 來刪除image $ docker rmi 918c36e ``` ![](https://i.imgur.com/pzblG1r.png) ```bash= # 也可用 docker export [container ID] > xxxx.tar 來將container壓成tar檔分享傳送 $ docker export 07a933 > test.tar ``` 用 docker ps -a 查看container ![](https://i.imgur.com/9rhafAS.png) 執行 **docker export 07a933 > test.tar** 後,用ls查看檔案 ![](https://i.imgur.com/U30m4Ys.png) ```bash= # 接收到壓縮後的tar檔時可用 docker import - [新的image名稱] xxxx.tar , 來將tar存成image $ docker import - test < test.tar ``` 執行 **docker import - test < test.tar** 後,查看images ![](https://i.imgur.com/Q4OMtXV.png) #### 7. 將Container push 到 Docker Hub。 ![](https://i.imgur.com/NrsOCkM.png) ```bash= # 用 docker diff [名稱/ID]來查改修改過的內容 $ docker diff gitea_sw2 # or $ docker diff 07a933b ``` #### 8. 將Container push 到 Private Registery。 --- ## Docker Tips ### Network :::info * #### 查看所有網路及其子網段 ```bash= docker network inspect $(docker network ls -q) | grep -E 'Name|Subnet' ``` * #### 查找 172.20.0.0/16 被誰使用 ```bash= docker network inspect $(docker network ls -q) | grep -B 10 "172.20" ``` * ### Resource Parematers ![image](https://hackmd.io/_uploads/rkXa9PWebe.png) :::