docker學習筆記

全部內容來自重要記錄的複製,轉自於https://juejin.im/book/5b7ba116e51d4556f30b476chtml

搭建docker環境

安裝

以CentOS爲例,所需命令以下,包括了啓動mysql

$ sudo yum install yum-utils device-mapper-persistent-data lvm2
$
$ sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
$ sudo yum install docker-ce
$
$ sudo systemctl enable docker
$ sudo systemctl start docker

查看版本

查看 Docker 版本的命令:docker versionlinux

$ sudo docker version
Client:
 Version:           18.06.1-ce
 API version:       1.38
 Go version:        go1.10.3
 Git commit:        e68fc7a
 Built:             Tue Aug 21 17:23:03 2018
 OS/Arch:           linux/amd64
 Experimental:      false

Server:
 Engine:
  Version:          18.06.1-ce
  API version:      1.38 (minimum version 1.12)
  Go version:       go1.10.3
  Git commit:       e68fc7a
  Built:            Tue Aug 21 17:25:29 2018
  OS/Arch:          linux/amd64
  Experimental:     false

查看更多信息能夠用docker info這個命令nginx

配置國內鏡像源

由 Docker 官方提供的國內鏡像源web

registry.docker-cn.com

此地址的協議是https
Linux環境下,咱們能夠經過修改 /etc/docker/daemon.json ( 若是文件不存在,你能夠直接建立它 ) 這個 Docker 服務的配置文件達到效果。redis

{
    "registry-mirrors": [
        "https://registry.docker-cn.com"
    ]
}

配置後須要重啓來生效sql

$ sudo systemctl restart docker

再經過docker info來查看,發現配置已生效docker

$ sudo docker info
# ......
Registry Mirrors:
 https://registry.docker-cn.com/
# ......

鏡像

之因此鏡像一般直接採用軟件名,這還要回歸到 Docker 對容器的輕量化設計中。Docker 對容器的設計和定義是微型容器而不是龐大臃腫的完整環境 ( 這固然歸功於容器技術在實現虛擬化過程當中性能幾乎無損 ),這就使得咱們一般會只在一個容器中運行一個應用程序,這樣的好處天然是可以大幅下降程序之間相互的影響,也有利於利用容器技術控制每一個程序所使用的資源。數據庫

搜索鏡像

  1. https://hub.docker.com/中能夠直接從中央倉庫中搜索鏡像
  2. 使用docker search tomcat命令也能夠查找相應的鏡像

若是不想下載最新的,而是指定鏡像的tag(冊子裏也說了,其實就是想指定某個軟件的版本進行下載),能夠參考:https://www.linuxidc.com/Linux/2019-03/157690.htmjson

獲取鏡像

# 這樣獲取到的是最新的
sudo docker pull ubuntu

# 也能夠像這樣指定版本獲取
sudo docker pull openresty/openresty:1.13.6.2-alpine

查看現有鏡像

docker images

管理鏡像

上面的docker images只能查看鏡像列表,若是想查看本地某個鏡像的詳情,能夠以下:

sudo docker inspect redis:3.2

刪除鏡像

sudo docker rmi ubuntu:latest

# 也能夠一次刪除多個鏡像,中間空格
sudo docker rmi redis:3.2 redis:4.0

刪除鏡像的過程實際上是刪除鏡像內的鏡像層,在刪除鏡像命令打印的結果裏,咱們能夠看到被刪除的鏡像層以及它們的 ID。固然,若是存在兩個鏡像共用一個鏡像層的狀況,你也不須要擔憂 Docker 會刪除被共享的那部分鏡像層,只有當鏡像層只被當前被刪除的鏡像所引用時,Docker 纔會將它們從硬盤空間中移除。

容器

容器的生命週期

  • Created:容器已經被建立,容器所需的相關資源已經準備就緒,但容器中的程序還未處於運行狀態。
  • Running:容器正在運行,也就是容器中的應用正在運行。
  • Paused:容器已暫停,表示容器中的全部程序都處於暫停 ( 不是中止 ) 狀態。
  • Stopped:容器處於中止狀態,佔用的資源和沙盒環境都依然存在,只是容器中的應用程序均已中止。
  • Deleted:容器已刪除,相關佔用的資源及存儲在 Docker 中的管理信息也都已釋放和移除。

建立容器

# 這種是直接建立,沒有給它起名,在使用時若是指定 容器id 來使用,會很麻煩
sudo docker create nginx:1.12

# 在建立容器的時候指定下名字(給起了一個 nginx111 的名字)
# 補充一句,名字是惟一的,重複起相同的名字會報錯
sudo docker create --name nginx111 nginx:1.12

注:若是本地環境中沒有nginx,tag爲1.12的鏡像,會直接從中央倉庫pull,而後再進行建立容器

啓動容器

# 由於建立時指定了名字,因此啓動時能夠經過名稱來啓動
sudo docker start nginx111

下面粘貼了幾張啓動時的截圖,能夠方便啓動後的狀態變化

也能夠用docker run命令,將docker createdocker start合併成一步,提高效率

sudo docker run --name nginx -d nginx:1.12

這裏須要注意的一點是,一般來講咱們啓動容器會指望它運行在「後臺」,而docker run在啓動容器時,會採用「前臺」運行這種方式,這時候咱們的控制檯就會銜接到容器上,不能再進行其餘操做了。咱們能夠經過-d--detach這個選項告訴 Docker 在啓動後將程序與控制檯分離,使其進入「後臺」運行。

管理容器

# 查看當前正在運行的容器
sudo docker ps

# 查看當前全部容器(-a <==> --all)
sudo docker ps -a

若是經過-a來啓動,能夠看到全部容器,status中是當前容器的運行狀態
這裏面有幾個選項:

  • Created 此時容器已建立,但尚未被啓動過。
  • Up [ Time ] 這時候容器處於正在運行狀態,而這裏的 Time 表示容器從開始運行到查看時的時間。
  • Exited ([ Code ]) [ Time ] 容器已經結束運行,這裏的 Code 表示容器結束運行時,主程序返回的程序退出碼,而 Time 則表示容器結束到查看時的時間。

中止容器

# 中止後,能夠再經過docker start來啓動
sudo docker stop nginx

刪除容器

sudo docker rm nginx

可是容器在運行時不容許被刪除,能夠經過-f的選項強行刪除

sudo docker rm -f nginx

進入容器

# 進入到以前建立的nginx這個容器
sudo docker exec -it nginx bash

在藉助 docker exec 進入容器的時候,咱們須要特別注意命令中的兩個選項不可或缺,即 -i 和 -t ( 它們倆能夠利用簡寫機制合併成 -it )。
其中 -i ( --interactive ) 表示保持咱們的輸入流,只有使用它才能保證控制檯程序可以正確識別咱們的命令。而 -t ( --tty ) 表示啓用一個僞終端,造成咱們與 bash 的交互,若是沒有它,咱們沒法看到 bash 內部的執行結果。

退出容器

進入後直接按ctrl+d便可退出

爲容器配置網絡

目前 Docker 官方爲咱們提供了五種 Docker 網絡驅動,分別是:Bridge Driver、Host Driver、Overlay Driver、MacLan Driver、None Driver

比較經常使用的就是BridgeOverlay

容器互聯

在建立容器時,經過在docker createdocker run命令中,添加--link參數,指定容器名,就能夠鏈接到相應容器上

$ sudo docker run -d --name mysql -e MYSQL_RANDOM_ROOT_PASSWORD=yes mysql
$ sudo docker run -d --name webapp --link mysql webapp:latest

這時,若是webapp應用,若是想要鏈接mysql數據庫,以下:

String url = "jdbc:mysql://mysql:3306/webapp";

暴露端口

有點相似開防火牆功能,給防火牆開個端口號
先看下mysql默認的,默認只開放了3306和33060端口:

$ sudo docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                 NAMES
95507bc88082        mysql:5.7           "docker-entrypoint.s…"   17 seconds ago      Up 16 seconds       3306/tcp, 33060/tcp   mysql

要開放更多的端口,能夠用--expose選項:

sudo docker run -d --name mysql -e MYSQL_RANDOM_ROOT_PASSWORD=yes --expose 13306 --expose 23306 mysql:5.7

再查看下開放的端口:

$ sudo docker ps 
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                                       NAMES
3c4e645f21d7        mysql:5.7           "docker-entrypoint.s…"   4 seconds ago       Up 3 seconds        3306/tcp, 13306/tcp, 23306/tcp, 33060/tcp   mysql

別名鏈接

# --link <name>:<alias>(前面是鏈接的容器名,後面是給起的別名)
$ sudo docker run -d --name webapp --link mysql:database webapp:latest

這樣能夠經過別名來鏈接

String url = "jdbc:mysql://database:3306/webapp";

管理網絡

若是不指定網絡,默認會把建立的容器添加到一個默認的bridge的網絡。而默認同一個網絡內是能互相通訊的,但不一樣網絡間是不能通訊的

# 能夠經過docker inspect來查看網絡
$ sudo docker inspect mysql
[
    {
# ......
        "NetworkSettings": {
# ......
            "Networks": {
                "bridge": {
                    "IPAMConfig": null,
                    "Links": null,
                    "Aliases": null,
                    "NetworkID": "bc14eb1da66b67c7d155d6c78cb5389d4ffa6c719c8be3280628b7b54617441b",
                    "EndpointID": "1e201db6858341d326be4510971b2f81f0f85ebd09b9b168e1df61bab18a6f22",
                    "Gateway": "172.17.0.1",
                    "IPAddress": "172.17.0.2",
                    "IPPrefixLen": 16,
                    "IPv6Gateway": "",
                    "GlobalIPv6Address": "",
                    "GlobalIPv6PrefixLen": 0,
                    "MacAddress": "02:42:ac:11:00:02",
                    "DriverOpts": null
                }
            }
# ......
        }
# ......
    }
]

建立網絡

docker CLI 裏與網絡相關的命令都以docker network開頭,其中建立網絡的命令是docker network create

# 建立了一個individual的網絡
$ sudo docker network create -d bridge individual

命令中經過-d來指定網絡類型,而網絡類型就是上面提到的那向種:bridge、host、overlay、maclan、none

查看存在的網絡

$ sudo docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
bc14eb1da66b        bridge              bridge              local
35c3ef1cc27d        individual          bridge              local

加入網絡

# 能夠經過--network individual來指定加入到individual網絡
$ sudo docker run -d --name mysql -e MYSQL_RANDOM_ROOT_PASSWORD=yes --network individual mysql:5.7

能夠再來查看下mysql所加入的網絡

$ sudo docker inspect mysql
[
    {
# ......
        "NetworkSettings": {
# ......
            "Networks": {
                "individual": {
                    "IPAMConfig": null,
                    "Links": null,
                    "Aliases": [
                        "2ad678e6d110"
                    ],
                    "NetworkID": "35c3ef1cc27d24e15a2b22bdd606dc28e58f0593ead6a57da34a8ed989b1b15d",
                    "EndpointID": "41a2345b913a45c3c5aae258776fcd1be03b812403e249f96b161e50d66595ab",
                    "Gateway": "172.18.0.1",
                    "IPAddress": "172.18.0.2",
                    "IPPrefixLen": 16,
                    "IPv6Gateway": "",
                    "GlobalIPv6Address": "",
                    "GlobalIPv6PrefixLen": 0,
                    "MacAddress": "02:42:ac:12:00:02",
                    "DriverOpts": null
                }
            }
# ......
        }
# ......
    }
]

端口映射

就是將容器的端口映身到宿主機上,經過外網訪問宿主機的端口,其實就是訪問到容器的那個端口

$ sudo docker run -d --name nginx -p 80:80 -p 443:443 nginx:1.12

使用端口映射選項的格式是-p <ip>:<host-port>:<container-port>,其中 ip 是宿主操做系統的監聽 ip,能夠用來控制監聽的網卡,默認爲0.0.0.0,也就是監聽全部網卡

咱們能夠將容器的 80 端口映射到宿主操做系統的 8080 端口,傳入-p 8080:80便可
而後咱們再查看下容器

$ sudo docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                                      NAMES
bc79fc5d42a6        nginx:1.12          "nginx -g 'daemon of…"   4 seconds ago       Up 2 seconds        0.0.0.0:80->80/tcp, 0.0.0.0:443->443/tcp   nginx

管理和存儲數據

以前說容器使用的原則是即停即刪,但容器中的數據怎麼辦?--冊子上說通常就是掛載到宿主機的磁盤中,使得即使刪除,數據也還在
掛載方式有三種:Bind MountVolumeTmpfs Mount

  • Bind Mount 可以直接將宿主操做系統中的目錄和文件掛載到容器內的文件系統中,經過指定容器外的路徑和容器內的路徑,就能夠造成掛載映射關係,在容器內外對文件的讀寫,都是相互可見的。
  • Volume 也是從宿主操做系統中掛載目錄到容器內,只不過這個掛載的目錄由 Docker 進行管理,咱們只須要指定容器內的目錄,不須要關心具體掛載到了宿主操做系統中的哪裏。
  • Tmpfs Mount 支持掛載系統內存中的一部分到容器的文件系統裏,不過因爲內存和容器的特徵,它的存儲並非持久的,其中的內容會隨着容器的中止而消失。

掛載到容器

使用-v--volume命令
-v <host-path>:<container-path> ,其中 host-path 和 container-path 分別表明宿主操做系統中的目錄和容器中的目錄。這裏的路徑要用絕對路徑,特別是<host-path>,若是僅僅是個名稱的話,就不是Bind Mount,而是Volume方式

$ sudo docker run -d --name nginx -v /webapp/html:/usr/share/nginx/html nginx:1.12

能夠查看下容器

$ sudo docker inspect nginx
[
    {
# ......
        "Mounts": [
            {
                "Type": "bind",
                "Source": "/webapp/html",
                "Destination": "/usr/share/nginx/html",
                "Mode": "",
                "RW": true,
                "Propagation": "rprivate"
            }
        ],
# ......
    }
]

能夠看到這裏的RW = true,也就是容器內的數據能夠寫文件到宿主機,若是隻讓容器只讀,能夠加:ro參數

$ sudo docker run -d --name nginx -v /webapp/html:/usr/share/nginx/html:ro nginx:1.12

掛載臨時文件目錄

因爲Tmpfs Mount這種方式是掛載到宿主機的內存中,因此不須要指定宿主機目錄,直接指定要掛載的容器目錄就能夠了

$ sudo docker run -d --name webapp --tmpfs /webapp/cache webapp:latest

這時再查看下詳情

$ sudo docker inspect webapp
[
    {
# ......
         "Tmpfs": {
            "/webapp/cache": ""
        },
# ......
    }
]

使用數據卷

其實也就是用 Volume方式掛載。由於是由Docker管理,不用去管他給掛載到宿主機的位置,但能夠經過操做數據卷的方式來操做它。

# 也是使用-v來掛載,只是直接指定容器的目錄便可
$ sudo docker run -d --name webapp -v /webapp/storage webapp:latest

使用docker inspect查看,其實就是掛載到了/var/lib/docker/volumes/目錄下。

$ sudo docker inspect webapp
[
    {
# ......
        "Mounts": [
            {
                "Type": "volume",
                "Name": "2bbd2719b81fbe030e6f446243386d763ef25879ec82bb60c9be7ef7f3a25336",
                "Source": "/var/lib/docker/volumes/2bbd2719b81fbe030e6f446243386d763ef25879ec82bb60c9be7ef7f3a25336/_data",
                "Destination": "/webapp/storage",
                "Driver": "local",
                "Mode": "",
                "RW": true,
                "Propagation": ""
            }
        ],
# ......
    }
]

可是上面沒有爲數據卷命名,因此咱們掛載時,能夠手動起一個數據卷名,規則:-v : 。若是該數據卷已存在,直接引用;沒有才去建立它

# 手動叫appdata的數據卷名
$ sudo docker run -d --name webapp -v appdata:/webapp/storage webapp:latest

共用數據卷

能夠給多個容器掛載到同一數據捲上(起同樣的名),這樣數據也就共享了

$ sudo docker run -d --name webapp -v html:/webapp/html webapp:latest
$ sudo docker run -d --name nginx -v html:/usr/share/nginx/html:ro nginx:1.12

數據卷管理

能夠直接經過docker volume xxx來操做數據卷

建立數據卷

$ sudo docker volume create appdata

查看數據卷

使用docker volume ls來查看

$ sudo docker volume ls
DRIVER              VOLUME NAME
local               html
local               appdata

刪除數據卷

可使用docker volume rm來刪除指定數據卷

$ sudo docker volume rm appdata

在刪除數據卷以前,咱們必須保證數據卷沒有被任何容器所使用 ( 也就是以前引用過這個數據卷的容器都已經刪除 ),不然 Docker 不會容許咱們刪除這個數據卷。

有些數據卷在建立時沒有指定名稱
這時刪除能夠用下面兩種方式:
1.在刪除容器時連帶着刪除它,使用-v命令便可

$ sudo docker rm -v webapp

2.使用docker volume prune,它能夠刪除那些沒有被容器引用的數據卷

$ sudo docker volume prune -f
Deleted Volumes:
af6459286b5ce42bb5f205d0d323ac11ce8b8d9df4c65909ddc2feea7c3d1d53
0783665df434533f6b53afe3d9decfa791929570913c7aff10f302c17ed1a389
65b822e27d0be93d149304afb1515f8111344da9ea18adc3b3a34bddd2b243c7
# ......
相關文章
相關標籤/搜索