關於網路那些事...

網路行銷,SEO,網路趨勢,教學文章,網頁設計,生活時事

Docker - Get Start Part 3. Services

這裡記錄 Services 實作流程

在之前,要先透過 part2 建立了 image gordon/get-started:part2

在這裡,建立 docker-compose.yml ,透過 image 來產生五個重複的 container

version: "3"
services:
  web:
    # replace username/repo:tag with your name and image details
    image: gordon/get-started:part2
    deploy:
      replicas: 5
      resources:
        limits:
          cpus: "0.1"
          memory: 50M
      restart_policy:
        condition: on-failure
    ports:
      - "4000:80"
    networks:
      - webnet
networks:
  webnet:

接著先執行 swarm 初始化(這部分會在 part 4 介紹)

docker swarm init

接著,執行建立 service app 名稱為 getstartedlab

docker stack deploy -c docker-compose.yml getstartedlab

查看是否執行成功,以及是否有實作五個重複

docker service ls

在這裡,因為我們使用的都是同樣的名稱來命名,因此這裏可以查詢執行中的5個 service 項目

docker service ps getstartedlab_web

也可以查看 container 執行狀況,來確定是否有5個container正在執行

docker container ls -q

接下來可以訪問 http://localhost:4000

這裡可透過 curl 直接查看,可以發現這時已經自動分配到不同的service host

curl http://localhost:4000
curl http://localhost:4000
curl http://localhost:4000
curl http://localhost:4000

停止app

docker stack rm getstartedlab

結束 swarm 任務

docker swarm leave --force

底下則是一些常用命令,可作為參考

docker stack ls                                            # List stacks or apps
docker stack deploy -c <composefile> <appname>  # Run the specified Compose file
docker service ls                 # List running services associated with an app
docker service ps <service>                  # List tasks associated with an app
docker inspect <task or container>                   # Inspect task or container
docker container ls -q                                      # List container IDs
docker stack rm <appname>                             # Tear down an application
docker swarm leave --force      # Take down a single node swarm from the manager

如果你喜歡我們的文章內容,請在這裡按個讚



Docker - Get Start Part 2. Containers

這裡記錄 Containers 實作流程

在這裡按照下方流程就能快速建立出一個 python demo web

預計將專案放置在 docker_project/get_started/

建立檔案: Dockerfile

# Use an official Python runtime as a parent image
FROM python:2.7-slim

# Set the working directory to /app
WORKDIR /app

# Copy the current directory contents into the container at /app
ADD . /app

# Install any needed packages specified in requirements.txt
RUN pip install --trusted-host pypi.python.org -r requirements.txt

# Make port 80 available to the world outside this container
EXPOSE 80

# Define environment variable
ENV NAME World

# Run app.py when the container launches
CMD ["python", "app.py"]

requirements.txt

Flask
Redis

app.py

from flask import Flask
from redis import Redis, RedisError
import os
import socket

# Connect to Redis
redis = Redis(host="redis", db=0, socket_connect_timeout=2, socket_timeout=2)

app = Flask(__name__)

@app.route("/")
def hello():
    try:
        visits = redis.incr("counter")
    except RedisError:
        visits = "<i>cannot connect to Redis, counter disabled</i>"

    html = "<h3>Hello {name}!</h3>" \
           "<b>Hostname:</b> {hostname}<br/>" \
           "<b>Visits:</b> {visits}"
    return html.format(name=os.getenv("NAME", "world"), hostname=socket.gethostname(), visits=visits)

if __name__ == "__main__":
    app.run(host='0.0.0.0', port=80)

這時,在資料夾內包含了 Dockerfile, app.py, requirements.txt 這三個檔案

透過下方指令建立 Docker image

docker build -t friendlyhello .

Docker 背景執行 friendlyhello

docker run -d -p 4000:80 friendlyhell

開啟瀏覽器,前往 http://0.0.0.0:4000

查看運行中的 container

docker ps

CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS                  NAMES
7dbb951f29b6        friendlyhello       "python app.py"     49 seconds ago      Up 54 seconds

停止運行指定的 docker

docker container stop 7dbb951f29b6

重新啟動

docker restart 7dbb951f29b6

關閉

docker stop 7dbb951f29b6

登入 Docker,輸入下方指令,並填寫帳號密碼登入你的 Docker

Docker login

註冊你的 images

docker tag image username/repository:tag

舉例來說:

docker tag friendlyhello gordon/get-started:part2

查看 images

$ docker image ls

REPOSITORY               TAG                 IMAGE ID            CREATED             SIZE
friendlyhello            latest              d9e555c53008        3 minutes ago       195MB
gordon/get-started         part2               d9e555c53008        3 minutes ago       195MB
python                   2.7-slim            1c7128a655f6        5 days ago          183MB

將 image 上傳

docker push gordon/get-started:part2

執行遠端的 repository

docker run -d -p 4000:80 gordon/get-started:part2

如果你喜歡我們的文章內容,請在這裡按個讚



Docker - 基本指令紀錄

Docker 基本操作常用的指令:

docker build -t friendlyhello .  # Create image using this directory's Dockerfile
docker run -p 4000:80 friendlyhello  # Run "friendlyname" mapping port 4000 to 80
docker run -d -p 4000:80 friendlyhello         # Same thing, but in detached mode
docker container ls                                # List all running containers
docker container ls -a             # List all containers, even those not running
docker container stop <hash>           # Gracefully stop the specified container
docker container kill <hash>         # Force shutdown of the specified container
docker container rm <hash>        # Remove specified container from this machine
docker container rm $(docker container ls -a -q)         # Remove all containers
docker image ls -a                             # List all images on this machine
docker image rm <image id>            # Remove specified image from this machine
docker image rm $(docker image ls -a -q)   # Remove all images from this machine
docker login             # Log in this CLI session using your Docker credentials
docker tag <image> username/repository:tag  # Tag <image> for upload to registry
docker push username/repository:tag            # Upload tagged image to registry
docker run username/repository:tag                   # Run image from a registry

如果你喜歡我們的文章內容,請在這裡按個讚



Docker - TMPFS

Docker Mount
下圖清楚了說明Docker host的 Volume with bind mounts 以及tmpfs mount 機制

這裡針對 tmpfs 部分進行介紹:

tmpfs mount

tmpfs mounts 只會儲存於host system的記憶體,不會寫入 host system的 filesystem。

因此,tmpfs mount 資料不會保存在硬碟、Docker host或 container 裡,只會存在container 執行的期間

通常會把 tmpfs mount 應用在非敏感或不必持續保留的狀態資料,舉例來說,swarm service 就是使用 tmpfs mount 去 mount secrets 到 service的 container。

在 Docker 17.06 以上版本,建議使用 --mount flag 來進行 bind mounts, volumes, 或者 tmpfs mount。

tmpfs 使用案例

tmpfs mounts 最適合使用於不必持續保留的資料,或者當你的應用程式需要寫入大量的非持續保留的資料時。在 host machine 或者 container,適當的採用 tmpfs mount 幾可以讓container執行效能提升。


如果你喜歡我們的文章內容,請在這裡按個讚



Docker - Bind Mounts

Docker Mount
下圖清楚了說明Docker host的 Volume with bind mounts 以及tmpfs mount 機制

這裡針對 Bind Mounts 部分進行介紹:

Bind Mounts

Bind mounts 在早期 Docker 版本就已經存在,相對於 volumes ,使用 Bind mounts 有一些功能限制:

當 container 在host machine 中的檔案或目錄使用 bind mount

host machine 是以完整的路徑來參照這些檔案或目錄

因此,在Docker host 中不需要存在這些檔案或目錄

若參照的目錄或檔案不存在,則會自動建立。

透過 Bind Mounts 的方式是非常有效率的方式,但使用 bind mounts 需要 host machine 有特定的 filesystem 結構才能運作

如果你正開發一個新的 Docker 應用程式,考慮改用 Volumes 時,就不能直接透過Docker CLI 來管理 bind mounts。

Bind mounts 可以指定在敏感的檔案

使用 bind mounts 其中一個特點就是,

你可以在 container 透過 processes running 來變更 host 的 filesystem,包括新增、修改、刪除重要的系統擋或路徑。

在安全性操作具有相當大的權限,包括可以在 host system 來操作影響非Docker的進程。

Bind Mounts 使用範例:

一般來說,會建議使用 Volumes

Bind mounts 具有以下的一些使用案例類型:

可以從 host machine 分享設定檔給 containers。

這特點有被Docker 運用在 container 預設的 DNS 解析處理,透過 host macine 來 mounting /etc/resolv.conf 到每一個 container。

在Docker host 以及 container 這兩個開發環境分享原始碼或檔案

舉例來說,當你的 container mount target/ 之後,以及每次你在 Docker host 上建立Maven時,container 都可以訪問這個被重新建構的目錄。

如果你使用這種方式來開發,你的 Dockerfile 產品將會生產後重新建構的文件直接複製到 Image,而不會使用 bind mount。

當Docker host 檔案或路徑結構需要保證透過 bind mounts 的方式時,就一定要用 Container。

注意事項

再使用 bind mounts 或者 volumes 都需要注意下列幾點:

  • 如果 container 所 mount 的位置已經存在檔案或目錄,這些內容一會被複製到 volume 裡。同樣的,如果你啟動 container 並且指定的 volume 尚未存在,將會建立一個空的 volume 。這樣的做法,對於多個 container 共用同一份 volume 時,會是最好的處理方式。
  • 如果 container mount 的 bin-mount 資料夾或目錄已經存在或 mount 的不是空的 volume,將會以模糊的方式來處理。舉例來說,如果當container mount 資料夾是/mnt ,在 Linux 這個資料夾同時會被用來 mounted USB Drive,在執行期間若 USB 移除,並不會影響已經 mount 的 bind mount或 volume。

如果你喜歡我們的文章內容,請在這裡按個讚



Docker - Volumes 介紹

Docker Mount

下圖清楚了說明Docker host的 Volume with bind mounts 以及tmpfs mount 機制

這裡針對 Volumes 部分進行介紹:


如果你喜歡我們的文章內容,請在這裡按個讚



Docker - 資料管理簡介

在 Docker 管理資料

在 container 所建立的檔案,預設都會存放在可容器寫入層(writable container layer)

這表示:

  • 當container不沒有運行時,資料就會跟著消失
  • container中的數據很難從外部取得
  • 可寫入容器層的資料,與container高度耦合,很難將資料搬移到其他地方
  • 需要透過 storage driver 來管理filesystem

當你建立一個新的 container,會同時在最上層建立一個新的可寫入層(writable layer),也稱為 container layer。

在 container內所有的改變都會在這裡面,例如: 建立新檔案,編輯檔案,刪除檔案,都會寫入這個容器可寫入層。


如果你喜歡我們的文章內容,請在這裡按個讚



Docker - Storage drivers

Docker - Storage drivers

為了能有效率的使用 storage drivers,一定要先了解 Docker builds 以及 stores images,container如何使用images。

Storage drivers可以允許你在容器可寫入層(container writable layer) 建立資料

但是,在 Storage driver 操作資料,有這些缺點:

  • 讀寫效率很差
  • 停止運行container之後,這些資料並不會保存

通常會透過 volumes 來保存資料以及改善效能問題

一個 storage driver 負責處理各layer之間的互動

container 與 image 最大的差別就在於頂層可寫入層,在container新增或修改的資料都會存在可寫入層,當container刪除,這個可寫入層就會一併刪除,這底層的 image 則不會影響。

主要是因為每一個 container 都擁有自己的可寫入層,而多個 containers 可以共享同一個 image

例如: 這裡顯示多個 containers 共享同一個 Ubuntu 15.04 image

因此,Storage driver 用來管理 image layers 以及 可寫入層的內容,

雖然所有的 sotrage dirver 處理的方式各有差異,但所有的 driver 使用的都是同樣的 image 堆疊,以及寫入時複製策略(copy-on-write (CoW) strategy)。

可以透過下方指令檢查目前 可寫入層的使用量

docker ps -s

寫入時複製策略 copy-on-write (CoW) strategy

若某一個資料位於底層image,

多個container 可直接訪問及讀取同一個檔案,當某個container修改內容時,系統會複製一個副本給這個container使用

此時,這個container修改的是副本檔案,其他 container 讀取的仍是原本的檔案

通常,若container沒有修改資源,這些多個呼叫者同時都只會讀取同一個檔案,以節省資源

共享 images

當執行 docker pull 或者建立container 發現 image 不存在需要額外 pull down時

新的 image 並不會儲存在 container,而是會儲存在Docker 在 local 的儲存空間,通常會位於 /var/lib/docker/

因此,首先執行的 Dockfiles 會先下載需要的 image (在image不存在local情況下)

接下來其他 Dockerfiles 執行,就會發現於 local 已經存在需要的 image,就會直接使用,而不需要再額外 pull image

可以透過 docker image ls 以及 docker history 檢驗 ID來自於同一個來源

複製策略讓 containers 更有效率

啟動 container時,會同時增加一個 container 可寫入層,在 container 對於資料變更修改都會儲存在這個地方

在原本 image 的原有存在的檔案則不會有任何改變,

若有變更檔案,則會複製一份出來,避免影響其他container

底下是官方參考步驟,來驗證這個流程

  1. 從terminal 執行 5個 docker run ,啟動5個 container ,同時執行完畢會列出這些 container ID
$ docker run -dit --name my_container_1 acme/my-final-image:1.0 bash \
  && docker run -dit --name my_container_2 acme/my-final-image:1.0 bash \
  && docker run -dit --name my_container_3 acme/my-final-image:1.0 bash \
  && docker run -dit --name my_container_4 acme/my-final-image:1.0 bash \
  && docker run -dit --name my_container_5 acme/my-final-image:1.0 bash

  c36785c423ec7e0422b2af7364a7ba4da6146cbba7981a0951fcc3fa0430c409
  dcad7101795e4206e637d9358a818e5c32e13b349e62b00bf05cd5a4343ea513
  1e7264576d78a3134fbaf7829bc24b1d96017cf2bc046b7cd8b08b5775c33d0c
  38fa94212a419a082e6a6b87a8e2ec4a44dd327d7069b85892a707e3fc818544
  1a174fc216cccf18ec7d4fe14e008e30130b11ede0f0f94a87982e310cf2e765
  1. 執行 docker ps 驗證這 5 個 container 確實有執行
$ docker ps
CONTAINER ID      IMAGE                     COMMAND     CREATED              STATUS              PORTS      NAMES
1a174fc216cc      acme/my-final-image:1.0   "bash"      About a minute ago   Up About a minute              my_container_5
38fa94212a41      acme/my-final-image:1.0   "bash"      About a minute ago   Up About a minute              my_container_4
1e7264576d78      acme/my-final-image:1.0   "bash"      About a minute ago   Up About a minute              my_container_3
dcad7101795e      acme/my-final-image:1.0   "bash"      About a minute ago   Up About a minute              my_container_2
c36785c423ec      acme/my-final-image:1.0   "bash"      About a minute ago   Up About a minute              my_container_1
  1. 列出 local 儲存的資料夾位置
$ sudo ls /var/lib/docker/containers

會看到這5個container ID 為名的資料夾

1a174fc216cccf18ec7d4fe14e008e30130b11ede0f0f94a87982e310cf2e765
1e7264576d78a3134fbaf7829bc24b1d96017cf2bc046b7cd8b08b5775c33d0c
38fa94212a419a082e6a6b87a8e2ec4a44dd327d7069b85892a707e3fc818544
c36785c423ec7e0422b2af7364a7ba4da6146cbba7981a0951fcc3fa0430c409
dcad7101795e4206e637d9358a818e5c32e13b349e62b00bf05cd5a4343ea513
  1. 檢查 size
$ sudo du -sh /var/lib/docker/containers/*
32K  /var/lib/docker/containers/1a174fc216cccf18ec7d4fe14e008e30130b11ede0f0f94a87982e310cf2e765
32K  /var/lib/docker/containers/1e7264576d78a3134fbaf7829bc24b1d96017cf2bc046b7cd8b08b5775c33d0c
32K  /var/lib/docker/containers/38fa94212a419a082e6a6b87a8e2ec4a44dd327d7069b85892a707e3fc818544
32K  /var/lib/docker/containers/c36785c423ec7e0422b2af7364a7ba4da6146cbba7981a0951fcc3fa0430c409
32K  /var/lib/docker/containers/dcad7101795e4206e637d9358a818e5c32e13b349e62b00bf05cd5a4343ea513

這些資料大小都是32k

因此,當我們啟動 container 時,Docker 不需要產生完整的image檔案,只需要建立一個輕薄的容器可寫入層,藉由這種方式獲得極大的效率


如果你喜歡我們的文章內容,請在這裡按個讚



Docker - Compose 介紹 (上)

Docker-Compose 是一個可以用來定義且執行多個 Container 應用程式的工具

可以很簡單的透過 Compose 的 yaml 來設定你的container應用程式

並且透過一個指令,就可以建立及啟動所有yaml設定的應用程式

Compose 可以在產品、階段產品、開發或測試項目使用

在使用上大致可以區分為三個過程:


如果你喜歡我們的文章內容,請在這裡按個讚



Docker - 安裝 MySQL

MySQL 是一個廣泛被使用,開源的關聯式資料庫管理系統( relational database management system, RDBMS)

目前的MySQL執行效能不斷提升,可靠且易於使用,

因此經常被作為網路應用程式開發資料庫的首選.

其中包括 Facebook, Twitter, YouTube, Yahoo 等公司都有使用。

詳細說明可參考官網: www.mysql.com.

這裡將說明如何在 Docker 安裝即執行 MySQL 環境


如果你喜歡我們的文章內容,請在這裡按個讚