Dockerfile & Docker Swarm & Docker Stack & Docker Compose 簡單理解

Dockerfile

通俗地講,它是爲了指導單個鏡像從無到有的構建過程。如果你鏡像是從Docker registry上面拉下來的,那就用不到這個文件;如果你是自己的應用,想打包成鏡像,那就需要這個文件。

Dockerfile資料:http://www.docker.org.cn/dockerppt/114.html

Docker Swarm

一句話,這個東西是用來搭建Docker集羣的。

示例:(兩臺已經安裝好Docker的機器:192.168.192.128 和 192.168.192.130

128上:(初始化爲Manager,然後開啓防火牆端口)

[root@localhost DockerComposeFolder]# docker swarm init
Swarm initialized: current node (pmio659q4pm90nlvtoe5ak293) is now a manager.

To add a worker to this swarm, run the following command:

    docker swarm join --token SWMTKN-1-17usxu5fddmp2laagvpatbgrq8tiigfj4ejgcmuof1oy942842-9r9jkrf33tico042cs684e886 192.168.192.128:2377

To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.

[root@localhost DockerComposeFolder]# firewall-cmd --zone=public --add-port=2377/tcp --permanent
success
[root@localhost DockerComposeFolder]# systemctl restart firewalld

130上:(加入集羣成爲一個Worker)

[root@localhost admin]# firewall-cmd --zone=public --add-port=2377/tcp --permanent
success
[root@localhost admin]# systemctl restart firewalld
[root@localhost admin]# docker swarm join --token SWMTKN-1-17usxu5fddmp2laagvpatbgrq8tiigfj4ejgcmuof1oy942842-9r9jkrf33tico042cs684e886 192.168.192.128:2377
This node joined a swarm as a worker.

128上:(列出節點列表)

[root@localhost DockerComposeFolder]# docker node ls
ID                            HOSTNAME                STATUS              AVAILABILITY        MANAGER STATUS      ENGINE VERSION
ply3z1rbyxn967zqdqltc5j7w     localhost.localdomain   Ready               Active                                  19.03.2
pmio659q4pm90nlvtoe5ak293 *   localhost.localdomain   Ready               Active              Leader              19.03.1

當前節點退出集羣

docker swarm leave --force

更新集羣

docker swarm update

應用示例:(在Learder上【128節點】

1. 編寫一個compose文件

[root@localhost DockerComposeFolder]# vim docker-compose-demo.yml

---

version: '3.7'

services:
  redis:
    image: redis
    ports:
      - "6379"
    deploy:
      replicas: 2
      update_config:
        parallelism: 2
        delay: 10s
      restart_policy:
        condition: on-failure
    networks:
      - swarmnet

  visualizer:
    image: dockersamples/visualizer:stable
    ports:
      - "8080:8080"
    stop_grace_period: 1m30s
    volumes:
      - "/var/run/docker.sock:/var/run/docker.sock"
    deploy:
      placement:
        constraints: [node.role == manager]
    networks:
      - swarmnet
networks: # 自定義網絡
  swarmnet:

2. 啓動

[root@localhost DockerComposeFolder]# docker stack deploy -c docker-compose-demo.yml my_first_app
Creating network my_first_app_swarmnet
Creating service my_first_app_visualizer
Creating service my_first_app_redis
[root@localhost DockerComposeFolder]# 

3. 查看

# stack列表
[root@localhost DockerComposeFolder]# docker stack ls
NAME                SERVICES            ORCHESTRATOR
my_first_app        2                   Swarm

# 服務列表
[root@localhost DockerComposeFolder]# docker service ls
ID                  NAME                      MODE                REPLICAS            IMAGE                             PORTS
w3a6mgfouljz        my_first_app_redis        replicated          2/2                 redis:latest                      *:30005->6379/tcp
pmakz6gwandv        my_first_app_visualizer   replicated          1/1                 dockersamples/visualizer:stable   *:8080->8080/tcp

4. 訪問Visualizer(Leader的IP:8080)記得開放防火牆端口

5. 停止stack

[root@localhost DockerComposeFolder]# docker stack rm my_first_app
Removing service my_first_app_redis
Removing service my_first_app_visualizer
Removing network my_first_app_swarmnet

6. 說明配置:deploy下的placement

配置這個可以規定服務的位置,如上面的結果,Visualizer只會在Manager上運行,而redis則會出現在Manager以及Worker上。

 

部署應用示例

打包鏡像參考:https://www.cnblogs.com/LUA123/p/11436805.html

注意,本示例中,web程序的開放端口是8081

1. 配置倉庫

因爲我們的本地應用倉庫在128上,如果130節點也想運行我們的web項目,那麼需要配置倉庫地址,不然找不到

vim /etc/docker/daemon.json
# 裏面是倉庫地址,根據情況自行修改
{
  "insecure-registries":["192.168.192.128:443"]
}

2. 編寫yml文件

version: '3.7'

services:
  web:
    image: 192.168.192.128:443/hello-2
    deploy:
      replicas: 2
      restart_policy:
        condition: on-failure
      resources:
        limits:
          cpus: "0.1"
          memory: 50M
    ports:
      - "8081:8081"
    networks:
      - swarmnet

  redis:
    image: redis
    ports:
      - "6379"
    deploy:
      replicas: 2
      update_config:
        parallelism: 2
        delay: 10s
      restart_policy:
        condition: on-failure
    networks:
      - swarmnet

  visualizer:
    image: dockersamples/visualizer:stable
    ports:
      - "8080:8080"
    stop_grace_period: 1m30s
    volumes:
      - "/var/run/docker.sock:/var/run/docker.sock"
    deploy:
      placement:
        constraints: [node.role == manager]
    networks:
      - swarmnet
networks: # 自定義網絡
  swarmnet:

啓動

[root@localhost DockerComposeFolder]# docker stack deploy -c docker-compose-demo.yml my_first_app
Creating network my_first_app_swarmnet
Creating service my_first_app_redis
Creating service my_first_app_visualizer
Creating service my_first_app_web

128節點查看

 

130節點查看

 

訪問128節點的Visualizer :http://192.168.192.128:8080/

打開8081防火牆端口後訪問

 

Docker Stack(Docker堆棧)

在上面的小例子已經有了體現。一句話,能夠一鍵部署一整套服務。

1. docker stack deploy 部署新的堆棧或者更新現有堆棧

docker stack deploy -c docker-compose-demo.yml my_first_app

-c:指定配置文件
my_first_app:指定stack名字

2. docker stack ls 顯示堆棧列表

[root@localhost DockerComposeFolder]# docker stack ls
NAME                SERVICES            ORCHESTRATOR
my_first_app        2                   Swarm

3. docker stack ps 列出堆棧中的任務

[root@localhost DockerComposeFolder]# docker stack ps my_first_app
ID                  NAME                        IMAGE                             NODE                    DESIRED STATE       CURRENT STATE           ERROR               PORTS
r41ww3p604z5        my_first_app_visualizer.1   dockersamples/visualizer:stable   localhost.localdomain   Running             Running 8 minutes ago                       
1jirtqlappdp        my_first_app_redis.1        redis:latest                      localhost.localdomain   Running             Running 8 minutes ago                       
yr4sz7k5uwpk        my_first_app_redis.2        redis:latest                      localhost.localdomain   Running             Running 8 minutes ago                       

4. docker stack services 列出堆棧中的服務

[root@localhost DockerComposeFolder]# docker stack services my_first_app
ID                  NAME                      MODE                REPLICAS            IMAGE                             PORTS
pmakz6gwandv        my_first_app_visualizer   replicated          1/1                 dockersamples/visualizer:stable   *:8080->8080/tcp
w3a6mgfouljz        my_first_app_redis        replicated          2/2                 redis:latest                      *:30005->6379/tcp

5. docker stack rm 刪除一個或多個堆棧

[root@localhost DockerComposeFolder]# docker stack rm my_first_app
Removing service my_first_app_redis
Removing service my_first_app_visualizer
Removing network my_first_app_swarmnet

 

Docker Compose

它是爲了指導單個“服務”的構建過程,“服務”實際上包含一個或者多個運行狀態下的容器。在服務中運行的單個容器稱爲任務,每個任務的ID是數字唯一遞增的。一般你的應用都需要依賴很多其它的環境,比如:數據庫啊、redis啊、zookeeper啊等等,你也可以一個一個配置參數啓動,但是有了docker-compose,你只需要把事先準備的好的配置寫在文件裏,然後docker-compose up一鍵啓動即可,相比一個一個手動啓動,方便了很多也減少了出錯機會。你會發現,它和Docker Stack的作用差不多。區別如下:

stack部署到集羣(配合swarm),compose只能部署到一個節點。

stack會跳過build過程,所以stack只能使用現成的鏡像;compose不會跳過build,所以compose對開發人員比較友好。

雖然compose也能進行生產環境的部署,但是在集羣角度來看,stack更適合生產部署。

詳解docker-compose.yml文件

version

 

查看Docker信息執行:docker info 或者 docker --version

[root@localhost admin]# docker --version
Docker version 19.03.1, build 74b1e89

提醒:你可以結合docker 命令(比如:build、run、network等等)來理解docker-compose

Run命令:https://docs.docker.com/engine/reference/commandline/run/

Docker-Compose-File:https://docs.docker.com/compose/compose-file/

以下選項是 docker-compose up 支持,而docker stack deploy 不支持的

build
cgroup_parent
container_name
devices
tmpfs
external_links
links
network_mode
restart
security_opt
sysctls
userns_mode

compose文件(包含大部分選項)

version: "3.7"
services:
  webapp:
    # build,構建一個鏡像(利用docker-compose執行此文件);如果在集羣模式下部署,將忽略此項,docker stack僅僅接受預先構建好的鏡像。
    build:
      # 包含Dockerfile的路徑,當提供的是相對路徑,解釋爲相對於compose文件的位置。
      context: ./dir
      # Compose使用指定的Dockerfile文件來構建
      dockerfile: Dockerfile-alternate
      # 構建參數,這些參數只能在構建過程中訪問
      args:
        - buildno=1
        - hash=cdc3b19
      # 緩存(v3.2開始)
      cache_from:
        - alpine:latest
      # 構建指定階段的Dockerfile(v3.4開始。參考:多階段構建文檔:https://docs.docker.com/develop/develop-images/multistage-build/)
      target: prod
      # 指定生成的容器中/dev/shm分區的大小(v3.5開始。可以爲字符串'1gb'或者整數數字1000000)
      shm_size: '1gb'

    # build或者指定鏡像的話,此項爲鏡像名稱
    image:app:tag
    # 容器標籤(也可以這樣寫 com.example.description: "Accounting webapp")
    labels:
      - "com.example.description=Accounting webapp"
    # 添加容器功能(執行man 7 capabilities查看全部)
    cap_add:
      - ALL
    # 刪除容器功能
    cap_drop:
      - NET_ADMIN
      - SYS_ADMIN
    # 爲容器指定可選的父cgroup
    cgroup_parent: m-executor-abcd
    #覆蓋默認命令(也可以是個列表,類似於Dockerfile:command: ["bundle", "exec", "thin", "-p", "3000"])
    command: bundle exec thin -p 3000
    # 默認docker-compose up 會按照順序啓動服務,如果你有前後順序,可以指定這個參數,代表db和redis先於webapp啓動
    depends_on:
      - db
      - redis
    # 部署(僅限v3版本,並且只適合集羣部署(docker stack),docker-compose up 將忽略這個選項)
    deploy:
      # 啓動容器副本數
      replicas: 6
      # 資源限制
      resources:
        # 不超過單核CPU的50%可用處理時間 & 不超過50M內存
        limits:
          cpus: '0.50'
          memory: 50M
        # 始終可用25%CPU時間 & 20M內存
        reservations:
          cpus: '0.25'
          memory: 20M
      # 重啓策略
      restart_policy:
        # 重啓時機(none、on-failure、any,默認any)
        condition: on-failure
        # 重啓嘗試的等待時間
        delay: 5s
        # 最大重試次數(默認永遠重試)
        max_attempts: 3
        # 在決定重新啓動是否成功之前等待多長時間(默認立即決定)
        window: 120s
      # 配置服務如何更新
      update_config:
        # 一次更新的容器數
        parallelism: 2
        # 更新一組容器之間的等待時間
        delay: 10s
      # 服務標籤
      labels:
        com.example.description: "This label will appear on the web service"
    # 覆蓋默認的entrypoint
    entrypoint: /code/entrypoint.sh
    # 從文件添加環境變量。可以是單個值(env_file: .env)或列表,文件內容每一行都是var=val格式化的,# 開頭的和空行都被忽略
    env_file:
      - ./common.env
      - ./apps/web.env
      - /opt/secrets.env
    # 添加環境變量,如果是布爾值要用引號括起來
    environment:
      - RACK_ENV=development
      - SHOW=true
      - SESSION_SECRET
    # 暴露端口但是不把它們發佈到主機,它們只能被鏈接服務訪問。只能指定內部端口。
    expose:
      - "3000"
      - "8000"
    # 鏈接到外部的容器(格式爲 容器名稱:別名)
    external_links:
      - redis_1
      - project_db_1:mysql
      - project_db_1:postgresql
    # 添加主機名映射
    extra_hosts:
      - "somehost:162.242.195.82"
      - "otherhost:50.31.209.229"
    # 日誌
    logging:
      # 驅動(默認json-file,還可以爲syslog和none)
      driver: "json-file"
      options:
        # 日誌最大大小,以及文件數量
        max-size: "200k"
        max-file: "10"
    # 網絡(要引入頂級配置的network)
    networks:
     - some-network
     - other-network
    # 暴露端口,以HOST:CONTAINER格式映射端口
    ports:
      - "3000"
      - "3000-3005"
      - "8000:8000"
      - "9090-9091:8080-8081"
      - "49100:22"
      - "127.0.0.1:8001:8001"
    # 重啓("no",always,on-failure,unless-stopped)
    restart: "no"
    # 設置內核參數
    sysctls:
      - net.core.somaxconn=1024
      - net.ipv4.tcp_syncookies=0
    # 將容器目錄映射到主機目錄(格式 HOST:CONTAINER)
    volumes:
      - "/var/run/postgres/postgres.sock:/var/run/postgres/postgres.sock"
      - "dbdata:/var/lib/postgresql/data"

  redis:
    image: redis
  db:
    image: postgres

# 配置網絡
networks:
  some-network:
  other-network:
    external:
      name: actual-name-of-network

 

後記:若是去理解這幾個東西,很好理解,但是如何靈活運用,就需要積累了(說實話官方給的文檔比較節省筆墨,有很多地方看了N遍也不明所以,還是自己要多去實踐)

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章