1. 程式人生 > 其它 >docker的學習(七)-docker深入學習

docker的學習(七)-docker深入學習

技術標籤:docker

四、docker高階知識

4.1 執行一個 web 應用

前面我們執行的容器並沒有一些什麼特別的用處。

接下來讓我們嘗試使用 docker 構建一個 web 應用程式。
我們將在docker容器中執行一個 Python Flask 應用來執行一個web應用。

[[email protected] ~]# docker pull training/webapp  # 載入映象
[[email protected] ~]# docker run -d -d -P training/webapp python app.py
WARNING: IPv4 forwarding is disabled. Networking will not work.
11c153984caa26e8dce7973e4ea79f6db6126689222a180c0a06593bf2594187
  • -d:讓容器在後臺執行。

  • -P:將容器內部使用的網路埠隨機對映到我們使用的主機上。

4.1.1 檢視 WEB 應用容器

使用 docker ps 來檢視我們正在執行的容器:

[[email protected] ~]# docker ps
CONTAINER ID   IMAGE             COMMAND           CREATED          STATUS         PORTS                     NAMES
11c153984caa   training/webapp   "python app.py"   11 seconds ago   Up 9 seconds   0.0.0.0:49154->5000/tcp   magical_saha

PORTS多了埠資訊。

0.0.0.0:49154->5000/tcp

Docker 開放了 5000 埠(預設 Python Flask 埠)對映到主機埠 49154上。

4.1.2 訪問驗證

在訪問驗證之前先調整一下配置,不然可能會出現無法訪問的問題

檢視ip轉發是否開啟
sysctl net.ipv4.ip_forward

顯示net.ipv4.ip_forward=0則表示未開啟。

開啟方式
vim /etc/sysctl.conf
# 增加一行
net.ipv4.ip_forward = 1
# 儲存檔案 shift ZZ
# 重新載入
# sysctl -p

這時我們可以通過瀏覽器訪問WEB應用

在這裡插入圖片描述
如果還不行,關閉防火牆試試

# 檢視防火牆狀態,runing為啟動
systemctl status firewalld.server
# 關閉防火牆
systemctl stop firewalld.server
# 禁用防火牆
systemctl stop firewalld.server

4.1.3 網路埠的快捷方式

通過 docker ps 命令可以檢視到容器的埠對映

[[email protected] ~]# docker ps 
CONTAINER ID   IMAGE             COMMAND           CREATED         STATUS         PORTS                    NAMES
724961f8f2ab   training/webapp   "python app.py"   6 minutes ago   Up 6 minutes   0.0.0.0:5000->5000/tcp   nervous_carson

docker 還提供了另一個快捷方式 docker port

  • 使用 docker port 可以檢視指定 (ID 或者名字)容器的某個確定埠對映到宿主機的埠號。

上面我們建立的 web 應用容器 ID 為 724961f8f2ab 的name為 nervous_carson

可以使用 docker port bf08b7f2cd89docker port wizardly_chandrasekhar來檢視容器埠的對映情況。

[[email protected] ~]# docker port 724961f8f2ab
5000/tcp -> 0.0.0.0:5000
[[email protected] ~]# docker port nervous_carson
5000/tcp -> 0.0.0.0:5000

4.1.4 檢視 WEB 應用程式日誌

docker logs [ID或者名字] 可以檢視容器內部的標準輸出。

[[email protected] ~]# docker logs -f 724
 * Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)
192.168.88.163 - - [18/Jan/2021 06:02:05] "GET / HTTP/1.1" 200 -
192.168.88.163 - - [18/Jan/2021 06:02:06] "GET /favicon.ico HTTP/1.1" 404 -
  • -f: 讓 docker logs 像使用 tail -f 一樣來輸出容器內部的標準輸出。

從上面,我們可以看到應用程式使用的是 5000 埠並且能夠檢視到應用程式的訪問日誌。

4.1.5 檢視WEB應用程式容器的程序

我們還可以使用 docker top 來檢視容器內部執行的程序

[[email protected] ~]# docker top 72496
UID                 PID                 PPID                C                   STIME               TTY                 TIME                CMD
root                25038               25018               0                   00:55               ?                   00:00:00            python app.py

4.1.6 檢查 WEB 應用程式

使用 docker inspect 來檢視 Docker 的底層資訊。它會返回一個 JSON 檔案記錄著 Docker 容器的配置和狀態資訊。包括容器id、內部網路和ip地址等

[[email protected] ~]# docker inspect 724
[
    {
        "Id": "724961f8f2ab3c7266abdf5ceff2cf55673520afced2b7affbac945dbc650c39",
        "Created": "2021-01-18T05:55:12.264342106Z",
        "Path": "python",
        "Args": [
            "app.py"
        ],
        "State": {
            "Status": "running",
            "Running": true,
    
此處省略......

4.2 Docker 容器連線

前面我們實現了通過網路埠來訪問執行在 docker 容器內的服務。

容器中可以執行一些網路應用,要讓外部也可以訪問這些應用,可以通過 -P 或 -p 引數來指定埠對映。

並且已經通過埠連線到一個 docker 容器,下面學習一下其他的連線方式

4.2.1 網路埠對映

在前面我們已經建立了一個 python 應用的容器。

[[email protected] ~]# docker images
REPOSITORY                          TAG       IMAGE ID       CREATED         SIZE
training/webapp                     latest    6fae60ef3446   5 years ago     349MB

並且使用-P 引數建立一個容器,通過 docker ps 可以看到容器埠 5000 繫結主機埠 49154。

我們也可以使用 -p標識來指定容器埠繫結到主機埠。
兩種方式的區別是:

  • -P :是容器內部埠隨機對映到主機的高階口。
  • -p : 是容器內部埠繫結到指定的主機埠。

例:容器內部的 5000 埠對映到我們本地主機的 5000 埠上。

[[email protected] ~]# docker run -d -p 5000:5000 training/webapp python app.py
68a8bf0a9b978e58904049da5bb9801ba7e73b0e8441367c036a86098964a879
docker: Error response from daemon: driver failed programming external connectivity on endpoint goofy_visvesvaraya (e0c75e5ad3794ea85e2f4f3d04b5dba69a7819b7b6ecf428fe7e07c23c15612b):  (iptables failed: iptables --wait -t nat -A DOCKER -p tcp -d 0/0 --dport 5000 -j DNAT --to-destination 172.17.0.2:5000 ! -i docker0: iptables: No chain/target/match by that name.
 (exit status 1)).

報錯了,重啟一下docker服務就行
[[email protected] ~]# systemctl restart docker
[[email protected] ~]# docker run -d -p 5000:5000 training/webapp python app.py
724961f8f2ab3c7266abdf5ceff2cf55673520afced2b7affbac945dbc650c39

在這裡插入圖片描述

我們可以指定容器繫結的網路地址,比如繫結 127.0.0.1。

[[email protected] ~]# docker run -d -p 127.0.0.1:5001:5000 training/webapp python app.py
e9ba94ff43f74ccd49bf005caad6765ebc770d08a6e7c11c41a64e31448e7c6e

$ curl http://127.0.0.1:5001/ ##訪問通過
$ curl http://localhost:5001/ ##訪問通過
$ curl http://192.168.88.84:5001/ ##訪問拒絕
curl: (7) Failed connect to 192.168.88.84:5001; 拒絕連線

從上面的測試中可以知道,要訪問容器中的應用只能通過127.0.0.1這個ip訪問容器的 5000 埠
接下來是繫結本機的任意埠到容器的80埠,docker會隨機分配一個埠

[[email protected] ~]# docker run -d -p 127.0.0.1::80 training/webapp python app.py
dee8072509d19728d0f4d850105c02ceb947e389344dd1ab7ea1f3b08c75a963

[[email protected] ~]# docker ps
CONTAINER ID   IMAGE             COMMAND           CREATED              STATUS              PORTS                               NAMES
dee8072509d1   training/webapp   "python app.py"   About a minute ago   Up About a minute   5000/tcp, 127.0.0.1:49153->80/tcp   frosty_wilbur
e9ba94ff43f7   training/webapp   "python app.py"   7 minutes ago        Up 7 minutes        127.0.0.1:5001->5000/tcp            flamboyant_feynman

[[email protected] ~]# curl http://127.0.0.1:49153/
curl: (56) Recv failure: Connection reset by peer

失敗的原因可能是 Python Flask 程式本身的問題, Python Flask 預設為5000 埠,

[[email protected] ~]# docker run -d -p 127.0.0.1::5000 training/webapp python app.py
3bdc7439068faec51b2817930df49b7f0e4bdace3aa1bd70457188946b4ccd65
[[email protected] ~]# docker port 3bdc
5000/tcp -> 127.0.0.1:49154
[[email protected] ~]# curl 127.0.0.1:49154
Hello world!

還可以指定通訊協議,上面的例子中,預設都是繫結 tcp 埠,如果要繫結 UDP 埠,可以在埠後面加上 /udp

[[email protected] ~]# docker run -d -p 127.0.0.1:5000:5000/udp training/webapp python app.py
f029e7235829a093b3db44d2d07ef0a56a4e88de87d63cca5fe28f78d358a578
[[email protected] ~]# docker ps
CONTAINER ID   IMAGE             COMMAND           CREATED              STATUS              PORTS                                NAMES
f029e7235829   training/webapp   "python app.py"   About a minute ago   Up About a minute   5000/tcp, 127.0.0.1:5000->5000/udp   focused_galileo


修改已有Docker的埠對映
查詢要修改容器的容器Id

[[email protected] centos-test]# docker inspect 7e06 | grep Id
        "Id": "7e06bef1c5a72b251a702810c3b739f09333cfc1521407f8c1937bba5742514d",

進到/var/lib/docker/containers 目錄下找到與 Id 相同的目錄,修改 hostconfig.json 和 config.v2.json檔案:

[[email protected] centos-test]# cd /var/lib/docker/containers/7e06bef1c5a72b251a702810c3b739f09333cfc1521407f8c1937bba5742514d/

若該容器還在執行,先停掉docker stop 容器ID
停掉docker服務systemctl stop docker

修改hostconfig.json
找到"PortBindings":{}項,新增埠繫結"8888/tcp": [{"HostIp": "","HostPort": "8888"}],表示繫結埠8888

"PortBindings":{"20/tcp": [{"HostIp": "","HostPort": "20"}],"21/tcp": [{"HostIp": "","HostPort": "21"}],"80/tcp": [{"HostIp": "","HostPort": "80"}],"443/tcp": [{"HostIp": "","HostPort": "443"}],"888/tcp": [{"HostIp": "","HostPort": "888"}],"8888/tcp": [{"HostIp": "","HostPort": "8888"}]},

修改config.v2.json
Hostname的找到ExposedPorts項(若沒有就手動新增一個),加上要暴露的埠"8888/tcp":{},即8888

{"Hostname":"7e06bef1c5a7","Domainname":"","User":"","AttachStdin":false,"AttachStdout":false,"AttachStderr":false,"ExposedPorts":{"20/tcp":{},"21/tcp":{},"80/tcp":{},"443/tcp":{},"888/tcp":{},"8888/tcp":{}},

在這裡插入圖片描述
啟動容器服務

systemctl start docker

啟動容器

docker start 7e

檢視埠

[[email protected] ~]# docker port 7e
80/tcp -> 0.0.0.0:80
888/tcp -> 0.0.0.0:888
8888/tcp -> 0.0.0.0:8888
20/tcp -> 0.0.0.0:20
21/tcp -> 0.0.0.0:21
443/tcp -> 0.0.0.0:443

4.2.2 Docker 容器互聯

埠對映並不是唯一把 docker 連線到另一個容器的方法。

docker 有一個連線系統允許將多個容器連線在一起,共享連線資訊。

docker 連線會建立一個父子關係,其中父容器可以看到子容器的資訊。

4.2.2.1 新建網路

下面先建立一個新的 Docker 網路。

[[email protected] ~]# docker network create -d bridge test-net
4ebeed8954c7f2de25ea86e09e583b33ae1f7fe529021e97f8681efad49f3215

先檢視下docker網路,發現添加了一個test-net網路
[[email protected] ~]# docker network ls
NETWORK ID     NAME       DRIVER    SCOPE
2b4ba552df71   bridge     bridge    local
492a3147f7fc   host       host      local
4e9c3ec7cede   none       null      local
4ebeed8954c7   test-net   bridge    local

引數說明:

  • -d:引數指定 Docker 網路型別,有 bridge、overlay。
    其中 overlay 網路型別用於 Swarm mode,在本小節中你可以忽略它。

4.2.2.2 連線容器

執行一個容器並連線到新建的 test-net 網路:

[[email protected] ~]# docker run -itd --name test1 --network test-net centos /bin/bash
8bb60b1c46b8e225d9d97c167e9fd715a93506add95b0708850a59260e04ee0a

開啟新的終端,再執行一個容器並加入到 test-net 網路:
[[email protected] ~]# docker run -itd --name test2 --network test-net centos /bin/bash
550d72f553e508d77a9ab0836d566d9b3e71fb9fe9fbb9c0b8763b87a3123ead

下面通過 ping 來證明 test1 容器和 test2 容器建立了互聯關係。

[[email protected] ~]# docker exec -it test1 /bin/bash
[[email protected] /]# ping test2
PING test2 (172.18.0.3) 56(84) bytes of data.
64 bytes from test2.test-net (172.18.0.3): icmp_seq=1 ttl=64 time=0.070 ms
64 bytes from test2.test-net (172.18.0.3): icmp_seq=2 ttl=64 time=0.046 ms
64 bytes from test2.test-net (172.18.0.3): icmp_seq=3 ttl=64 time=0.086 ms

這樣,test1 容器和 test2 容器建立了互聯關係。

如果你有多個容器之間需要互相連線,推薦使用Docker Compose

4.2.2.3 配置 DNS

如果在容器啟動時沒有指定 --dns 和 --dns-search,Docker 會預設用宿主主機上的 /etc/resolv.conf 來配置容器的 DNS。

全域性dns配置

我們可以在宿主機的 /etc/docker/daemon.json 檔案中增加以下內容來設定全部容器的 DNS:

{
  "dns" : [
    "114.114.114.114",
    "8.8.8.8"
  ]
}

設定後,啟動容器的 DNS 會自動配置為 114.114.114.114 和 8.8.8.8。

配置完,需要重啟 docker 才能生效。

檢視容器的 DNS 是否生效可以使用以下命令,它會輸出容器的 DNS 資訊:

[[email protected] ~]# docker run -it --rm centos cat /etc/resolv.conf
nameserver 114.114.114.114
nameserver 8.8.8.8

手動指定容器的配置

如果只想在指定的容器設定 DNS,則可以使用以下命令:

$ docker run -it --rm -h host_centos --dns=114.114.114.114 --dns-search=test.com centos
引數說明:

  • –rm:容器退出時自動清理容器內部的檔案系統。
  • -h HOSTNAME 或者 --hostname=HOSTNAME: 設定容器的主機名,它會被寫到容器內的 /etc/hostname 和 /etc/hosts。
  • –dns=IP_ADDRESS: 新增 DNS 伺服器到容器的 /etc/resolv.conf 中,讓容器用這個伺服器來解析所有不在 /etc/hosts 中的主機名。
  • –dns-search=DOMAIN: 設定容器的搜尋域,當設定搜尋域為 .example.com 時,在搜尋一個名為 host 的主機時,DNS 不僅搜尋 host,還會搜尋 host.example.com。

4.3 dockerfile學習

關於dockerfile的基本使用在 3.1.5.2 使用Dockerfile建立映象 已經學過了,就不再寫了

4.3.1 dockerfile的指令詳解

dockerfire指令學習

4.4 docker實踐應用

寶塔

使用dockerfile構建一個寶塔面板映象

# This my first nginx Dockerfile
# Version 1.0

# Base images 基礎映象
FROM centos

#MAINTAINER 維護者資訊
MAINTAINER test-1

#RUN 執行以下命令 
Run yum install -y git
Run yum install -y wget && wget -O install.sh http://download.bt.cn/install/install_6.0.sh && sh install.sh -y

# 執行命令
CMD ["bt","default"]

emm~~~ 安裝失敗,因為寶塔安裝的時候還要手動輸入一個y,但在容器外輸入的時候容器無法接收到

Step 5/5 : RUN yum install -y wget && wget -O install.sh http://download.bt.cn/install/install_6.0.sh && sh install.sh
 ---> Running in 1f6536ea5a61
Last metadata expiration check: 19:38:53 ago on Tue Jan 19 06:00:31 2021.
Package wget-1.19.5-10.el8.x86_64 is already installed.
Dependencies resolved.
Nothing to do.
Complete!
--2021-01-20 01:39:25--  http://download.bt.cn/install/install_6.0.sh
Resolving download.bt.cn (download.bt.cn)... 123.129.198.197, 240e:ff:9000:1100:0:3:0:36
Connecting to download.bt.cn (download.bt.cn)|123.129.198.197|:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 25386 (25K) [application/octet-stream]
Saving to: 'install.sh'

     0K .......... .......... ....                            100% 2.49M=0.01s

2021-01-20 01:39:25 (2.49 MB/s) - 'install.sh' saved [25386/25386]


+----------------------------------------------------------------------
| Bt-WebPanel FOR CentOS/Ubuntu/Debian
+----------------------------------------------------------------------
| Copyright © 2015-2099 BT-SOFT(http://www.bt.cn) All rights reserved.
+----------------------------------------------------------------------
| The WebPanel URL will be http://SERVER_IP:8888 when installed.
+----------------------------------------------------------------------
y
y

^C

研究了一會,煩了,就用普通方式建立一個吧

[[email protected] centos-test]# docker run -itd --name bt_centos centos /bin/bash
7e06bef1c5a72b251a702810c3b739f09333cfc1521407f8c1937bba5742514d

[[email protected] centos-test]# docker exec -it  7e06 /bin/bash
[[email protected] /]# yum install -y wget && wget -O install.sh http://download.bt.cn/install/install_6.0.sh && sh install.sh
[[email protected] /]# exit                
exit
[[email protected] centos-test]# docker commit -m "add a new bt" -a "silentgrass" 7e06 silentgrass/btcebtos:v1 
sha256:6b99547dee16fd78177501af2efd73a95932b544ff72984c1f86f376ce56b934
[[email protected] centos-test]# docker images
REPOSITORY                          TAG       IMAGE ID       CREATED              SIZE
silentgrass/btcebtos                v1        6b99547dee16   About a minute ago   869MB

忘記指定埠了怎麼啟動呢
1.根據新封裝的映象建立寶塔容器

docker run -i -t -d --name baota -p 20:20 -p 21:21 -p 80:80 -p 443:443 -p 888:888 -p 8888:8888 --privileged=true -v /home/www:/www silentgrass/btcebtos 

2.修改要埠對映的容器的配置檔案 點此跳轉


- - - 高階應用over - - -

感謝

Docker埠對映外部無法訪問問題
docker埠對映或啟動容器時報錯Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen
Docker容器繫結外部IP和埠
docker容器新增對外對映埠
修改已有Docker的埠對映