---
# System prepended metadata

title: Docker 入門

---

# Docker 入門

## 三大概念
* image
* container
* repository

一個 image 可建立多個 container，container 可被啟動，開始，停止，刪除。repository 分為 public 和 private 的，類似 git 的概念。

### docker 服務
docker engine
docker volumes
docker networks

## 安裝

刪除舊版 docker
` sudo apt-get remove docker docker-engine docker.io containerd runc`

更新套件
`sudo apt-get update`

安裝必要的套件
`sudo apt-get install \`
`    apt-transport-https \`
`    ca-certificates \`
`    curl \`
`    gnupg-agent \`
`    software-properties-common`

加上 docker gpg key
`curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -`
`sudo apt-key fingerprint 0EBFCD88`

加入 docker repository
`sudo add-apt-repository \`
`   "deb [arch=amd64] https://download.docker.com/linux/ubuntu \`
`   $(lsb_release -cs) \`
`   stable"`

安裝 docker
`sudo apt-get update`
`sudo apt-get install docker-ce`

不用 sudo 也可以執行
`sudo usermod -aG docker $(whoami)`

## image
搜尋 image
`docker search ubuntu`

pull image
`docker pull ubuntu:16.04`

列出本地所有 image
`docker images`

刪除 image
`docker rmi ubuntu:16.04`

### dockerfile
dockerfile 中每一條指令會建立一層 image
用 # 寫註解。
FROM 指定用哪個 image 當作基底
ADD/COPY 複製本地檔案到 images
`ADD FROM-PATH TO-PATH`

ENV
`ENV DB_HOST LOCALHOST`
`ENV demoPATH="/var/log" demoVer="1.0"`

EXPOSE 向外部開放的 port
`EXPOSE 5000`

RUN 會在建立 image 的過程中執行。
`RUN mkdir -p /home/demo/docker`

`RUN apt-get update && \`
`    apt-get install ffmpeg -y &&\`
`    pip3 install -r /r.txt`

`RUN ["apt-get", "install", "python3"]`


CMD 為 container 啟動後執行的指令
會被docker run 覆蓋
`CMD echo "This is a test." | wc -`
`CMD ["/usr/bin/wc","--help"]`

用 bash 指令替代 CMD 內指定的指令
`docker run -ti nginx bash`

ENTRYPOINT 
不會被 docker run 覆蓋
`ENTRYPOINT ["executable", "param1", "param2"]`
`ENTRYPOINT command param1 param2`


從 dockerfile 產生 image
`docker build -f /path/to/a/Dockerfile -t myimage:v3 .`

WORKDIR 進入 container 後的 pwd
`WORKDIR /app`

VOLUME 

## container
列出目前執行中的 container
`docker ps`

終止狀態的 container 也會列出
`docker ps -a`

新建立並啟動 container
從 image 建立 container，並在其中執行 /bin/bash 指令
也可填入 image id
d 表示背景執行
`docker run -tid ubuntu:16.04 /bin/bash`
命名 container name
`docker run -p 4000:5000 --name xxxxx -itd ubuntu bash`

container 已存在時
`docker start ubuntu`
`docker restart ubuntu`
`docker stop ubuntu`

取得 container console 輸出的訊息
`docker logs containerID`
`docker stats containerID`
`docker inspect containerID`

container 背景執行後，可以再重新連接上
`docker exec -it alpine1 ip addr show` -> 執行 ip addr show 指令
`docker exec -ti containerid bash`  -> 用 exit 離開，仍會在背景執行
`docker attach containerid` -> 用 exit 離開，container 就會關閉。ctrl + p 再
ctrl + q, 就不會關閉

刪除已停止的 container
`docker rm containerid`

刪除正在執行的 container
`docker kill containerid`

## Docker Network

會產生 networkid
`docker network`
`docker network --name main_net`

`docker network inspect networkid`

`docker network ls`
`docker run -ti --name container1 --rm --network=main_net ubuntu`

### bridge (default)
預設會產生 docker0 的 network interface (可用 `ifconfig` 檢查)
* 在自訂的 docker network 中，container 可以透過 domain name 的方式與其他在同一個 docker network 下的 container 通訊
* 不同 docker network 之間的 container 網路是隔離無法相互通訊的，不論是透過 domain name or IP


## Docker Volume

### 先產生 volume，再掛進 container
會產生 volumeid
`docker volume create` 
`docker volume create --name db-volumeName`

兩個 container 之間可共用資料
`docker run -v volumeid:/foo --name foo -it ubuntu /bin/sh`
`docker run -v volumeid:/foo2 --name foo2 -it ubuntu /bin/sh`

`docker volume ls`
`docker volume inspect volumeid`

`docker inspect -f '{{.Mounts}}' containerName`

### 用 Dockfile 產生
`VOLUME /data`

### 用 run 指令產生
掛 volume
`docker run -v /data --name foo ubuntu /bin/bash`
掛本機資料夾
`docker run -v /home/admin/data:/data --name foo ubuntu /bin/bash`


## docker compose

### 安裝
`curl -L https://github.com/docker/compose/releases/download/1.25.4/docker-compose-`uname -s`-`uname -m` -o ~/docker-compose`
`sudo mv ~/docker-compose /usr/local/bin/docker-compose`
`sudo chmod +x /usr/local/bin/docker-compose`

`docker-compose.yml`

用 -f 指定特定的dockercompose file
--build 重新建構
`docker-compose up -d -f dockercomposefile --build`

`docker-compose ps`
`docker-compose logs`
`docker-compose logs servicename`
`docker-compose stop`
`docker-compose down`
`docker-compose rm`

`docker-compose images`
`docker-compose top`
`docker-compose ps`

attach shell，不需要 -it
`docker-compose exec servicename bash`

### docker-compose.yaml
version
要使用的 docker-compose 版本號

docker-compose 會使用 image or build 來建置docker-compose 基底，有 image 會先使用 image
image
要使用的基底image

build
直接取 Dockerfile
`build .`

指定特殊名稱的 dockerfile 
`build:`
    `context: .`
    `dockerfile: nginx.Dockerfile`

ports

volumes
可直接掛載本機的檔案到 container 內 or
先宣告在外面，再宣告在services內
宣告建立db_data儲存目錄
`volumes:`
    `db_data:`

`volumes:`
    `- db_data:/var/lib/mysql`

networks
定義 docker networks
先宣告在外面，再宣告在services內
`networks:`
    `mysql:`
    
`networks:`
    `- mysql`

environment
depends_on

## Kubernetes

### deployment 物件
project -> clusters -> nodes (類似 vm) -> pods -> containers

###  Service 物件
Pod 之間可以互相溝通，可從外部存取 cluster

https://philipzheng.gitbook.io/docker_practice/
https://ithelp.ithome.com.tw/users/20092025/ironman/2603
https://ithelp.ithome.com.tw/users/20111953/ironman/1938
https://godleon.github.io/blog/Docker/docker-network-overview/
https://godleon.github.io/blog/Docker/docker-network-bridge/
https://dotblogs.com.tw/grassshrimp_tech_intern/2016/06/20/194915
http://blog.maxkit.com.tw/2017/03/docker-volume.html
https://www.netadmin.com.tw/netadmin/zh-tw/technology/34E092358FA040B2A3DDB9E9597470DF
https://www.netadmin.com.tw/netadmin/Author.aspx?Id=222

正向代理和反向代理的區別

雖然正向代理伺服器和反向代理伺服器所處的位置都是客戶端和真實伺服器之間，所做的事情也都是把客戶端的請求轉發給伺服器，再把伺服器的響應轉發給客戶端，但是二者之間還是有一定的差異的。

1、正向代理其實是客戶端的代理，幫助客戶端訪問其無法訪問的伺服器資源。反向代理則是伺服器的代理，幫助伺服器做負載均衡，安全防護等。

2、正向代理一般是客戶端架設的，比如在自己的機器上安裝一個代理軟體。而反向代理一般是伺服器架設的，比如在自己的機器集群中部署一個反向代理伺服器。

3、正向代理中，伺服器不知道真正的客戶端到底是誰，以為訪問自己的就是真實的客戶端。而在反向代理中，客戶端不知道真正的伺服器是誰，以為自己訪問的就是真實的伺服器。

4、正向代理和反向代理的作用和目的不同。正向代理主要是用來解決訪問限制問題。而反向代理則是提供負載均衡、安全防護等作用。二者均能提高訪問速度。