---
# System prepended metadata

title: What is Docker?
tags: [docker, Container]

---

###### tags: `Container` `docker`

# What is Docker?

![](https://i.imgur.com/NMPDoH4.png)

[TOC]

## 前言

相信一般開發者每次開發應用程式時最討厭的就是設定環境。往往裝好環境時開發應用的熱情往往被消磨一半，不過如今有了 Docker 不但可以提高開發效率也可以更容易管理整個服務架構，發展 micro service！

## Docker 基本概念

Docker 和傳統在硬體做虛擬化的方式不同，其主要在作業系統層做虛擬化且在主流的作業系統和雲端平台上都可以使用（例如：Linux、MacOS 和 Windows），不同作業系統 Docker 相關安裝方式可以參考官方網站。

![](https://i.imgur.com/jj7Dh1o.png)

關於 Docker 基本有三大主軸概念：

Docker 映像檔（Image）：類似於虛擬機的映像檔，是一個可以創建容器的模版（template）
Docker 容器（Container）：類似於一個輕量級 sandbox。Docker 是透過容器來運行並隔離應用
Docker 倉庫（Repository）：類似於程式碼儲存地，可以想成是 Docker 版的 git repo。而 Docker Hub 類似於 Docker 版的 Gihub，有許多 repo 在上面分享

![](https://i.imgur.com/uO6vtUP.png)


## 常用指令

### 啟動Docker容器

docker run 可以用來啟動 Docker 虛擬容器環境：

```bash
# 啟動 Docker 容器
docker run -it tensorflow/tensorflow bash
```

加上 -it 參數代表在執行 Docker 虛擬容器環境時，開啟虛擬終端機，以互動的模式執行。這個例子是執行一個 TensorFlow 的 Docker 容器，並且在 Docker 中執行 bash。

### 列出所有Docker容器

docker ps 可以列出所有 Docker 容器的資訊：

```bash
# 列出所有 Docker 容器
$ docker ps
CONTAINER ID        IMAGE                   COMMAND             CREATED              STATUS              PORTS                NAMES
d9b6f31bd21d        tensorflow/tensorflow   "bash"              About a minute ago   Up About a minute   6006/tcp, 8888/tcp   elated_panini
```

從輸出中可以看到這個新的 Docker 容器 ID 為 d9b6f31bd21d。

### 停止 Docker 容器

若要停止 Docker 容器，可以使用 stop 指令：

```bash
# 停止 Docker 容器
docker stop DOCKER_ID
其中 DOCKER_ID 就是 Docker 容器的 ID。
```

如果 Docker 容器當掉，可以考慮改用 kill：

```bash
# 強制停止 Docker 容器
docker kill DOCKER_ID
```

### 重新啟動 Docker 容器

若要重新啟動 Docker 容器，則可使用 restart：

```bash
# 重新啟動 Docker 容器
docker restart DOCKER_ID
```

### 暫停 Docker 容器

若要暫停 Docker 容器，可用：

```bash=
# 暫停 Docker 容器
docker pause DOCKER_ID
```

若要讓暫停的 Docker 容器恢復執行，則使用：

```bash=
# 恢復 Docker 容器
docker unpause DOCKER_ID
```

### 複製檔案

接著在實體機器（host）中使用 docker cp 指令，將檔案複製到該容器內：

```bash=
# 複製檔案
docker cp /path/to/file1 DOCKER_ID:/path/to/file2
```

這樣就會把實體機器的 /path/to/file1 複製到 Docker 容器中的 /path/to/file2。

Docker 容器內的預設路徑是根目錄（/），所以上面的指令也可以寫成：

```bash=
# 複製檔案
docker cp /path/to/file1 DOCKER_ID:path/to/file2
```
docker cp 的運作方式類似 Linux 系統的 cp -a 指令，也就是說它可以直接複製整個目錄以及其子目錄：

```bash=
# 複製檔案
docker cp /path/to/folder DOCKER_ID:/another/path/
```

這樣就會把實體機器的 /path/to/folder 目錄整個複製到 Docker 容器中的 /another/path/。

若要把 Docker 容器內的檔案複製出來，也是使用類似的做法：

```bash=
# 複製檔案
docker cp DOCKER_ID:/path/to/file1 /path/to/file2
```

這樣就可以把 Docker 容器內的 /path/to/file1 複製到實體機器的 /path/to/file2。目錄的複製方法也相同：

```bash=
# 複製目錄
docker cp DOCKER_ID:/path/to/folder /path/to/
```

### 掛載目錄

如果想要將實體機器的目錄直接掛載至 Docker 容器內，可以使用 -v 參數：

```bash=
# 掛載目錄
docker run -it -v /home/seal/data:/data tensorflow/tensorflow bash
```

這樣就會將實體機器的 /home/seal/data 掛載至 Docker 容器內的 /data，讓實體機器與 Docker 容器可以共享同一個目錄，在 Docker 容器中將資料放進這個目錄時，於實體機器中可以同時看見，反之亦然。

### 限制 CPU 使用量

Docker 預設並不會限制容器的 CPU 使用量，也就是說實體機器有多少 CPU 核心，Docker 容器就可以使用多少。若要限制 Docker 容器的 CPU 使用量，可以使用 --cpus 來指定可用的 CPU 數量：

```bash=
# 限制 CPU 使用量
docker run -it --cpus=1.5 agileek/cpuset-test
```

這樣就會限制 Docker 容器最多只能使用到 1.5 顆實體的 CPU。

### 限制記憶體使用量

記憶體的狀況與 CPU 類似，預設都沒有任何限制，若要限制記憶體與 swap 交換空間的用量，可以使用 --memory 與 --memory-swap 參數：

```bash=
# 限制記憶體使用量
docker run -it --memory=300m --memory-swap=1g tensorflow/tensorflow bash
```

這樣就會允許 Docker 容器使用 300m 的記憶體，以及 1g - 300m = 700m 的 swap 交換空間。

### 網路連接埠

如果要讓 Docker 容器內部的服務可以接收來自於外部的網路連線，可以使用 -p 參數將 Docker 容器內部的連接埠對應到實體機器的連接埠：

```bash=
# 設定網路連接埠對應
docker run -it -p 80:8888 tensorflow/tensorflow
```

這樣就會將 Docker 容器的 8888 連接埠，對應到實體機器的 80 連接埠。

這是將 Docker 容器的 8080 連接埠與實體機器 127.0.0.1 的 80 連接埠的例子：

```bash=
# 設定網路連接埠對應
docker run -p 127.0.0.1:80:8080 ubuntu bash
```

### 查看 Docker 容器的 CPU、記憶體與網路用量

若要查看 Docker 容器的 CPU、記憶體與網路用量，可以使用 stats：

```bash=
# 查看 CPU、記憶體與網路用量
docker stats
```

### 查看 Docker 容器內部的行程

若要查看 Docker 容器內部的行程，可以使用 top：

```bash=
# 查看 Docker 容器內部的行程
docker top DOCKER_ID
```

### Container內執行指令

```bash=
$ docker exec -it nginx bash
```

## 實際演練

### Nginx Web Server

```bash=
$ docker run -p 7777:80 -v index.html:/usr/share/nginx/html:ro -d --name nginx-container nginx
```

### DB2

```bash=
$ docker run -itd --privileged=true -p 50000:50000 -e LICENSE=accept -e DB2INST1_PASSWORD=db2inst1 -e DBNAME=ALARMDB -v ~/developer/tmp/db2data:/database --name db2 ibmcom/db2:11.5.5.0
```

### SCM Manager

```bash=
$ docker run --name scm -p 8090:8080 -v D:\\scm-home:/var/lib/scm scmmanager/scm-manager
```


