Docker入門的億點點學習

不想只會CURD的猿某人發表於2022-02-14

前段時間花了些時間學習了億點點docker,也算是入門了吧,順便記了一下筆記拿出來分享給想要接觸docker的兄弟們。

沒有伺服器的兄嘚可以去騰訊雲或者阿里雲領取免費的試用產品嗷,如果已經領取過了,又不想買伺服器的,那就去阿里雲的Linux體驗館吧,一次兩小時,除了每次使用都要重新下載環境以外,也還行?。阿里雲Linux體驗館地址:linux體驗館 (aliyun.com)

一、安裝docker

1.檢視是否已安裝docker列表

如果有則先解除安裝

yum list installed | grep docker        

2.安裝docker

詳細安裝步驟可以參考菜鳥教程:https://www.runoob.com/docker/centos-docker-install.html

1.更新yum(不是必須的,如果無法下載docker則需要更新)

yum update -y

2.安裝所需的軟體包

yum-utils 提供了 yum-config-manager ,並且 device mapper 儲存驅動程式需要 device-mapper-persistent-data 和 lvm2

sudo yum install -y yum-utils \ device-mapper-persistent-data \ lvm2    

3.設定docker包源地址(阿里雲國內源)

 sudo yum-config-manager \
    --add-repo \
    http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo

4.安裝docker

yum -y install docker-ce

5.阿里雲獲取容器映象加速

登入阿里雲,搜尋容器映象服務,開通後去控制檯找到映象加速器,複製並執行以下命令

image

sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
  "registry-mirrors": ["https://fc6uhvfa.mirror.aliyuncs.com"]
}
EOF
sudo systemctl daemon-reload
sudo systemctl restart docker

3.啟動docker

# 啟動docker
systemctl start docker    
# 檢視docker執行狀態
systemctl status docker
# 關閉docker
systemctl stop docker

二、解除安裝docker

1.停用docker

systemctl stop docker

2、檢視yum安裝的docker檔案包

yum list installed |grep docker

3.檢視docker相關的rpm原始檔

rpm -qa | grep docker

4、刪除所有安裝的docker檔案包

yum remove docker-ce docker-ce-cli containerd.io

刪完之後可以再檢視下docker rpm源

rpm -qa |grep docker

5、刪除docker的映象檔案,預設在/var/lib/docker目錄下

rm -rf /var/lib/docker

到此docker解除安裝就完成了,再執行docker -v就無法識別命令了。

三、docker基礎命令

一、映象操作

1.查詢映象

docker search 映象名稱

2.拉取映象

docker pull 映象名稱:版本號
例子:
docker pull redis
docker pull redis:5.0

3.檢視本地映象

docker images

4.刪除映象、刪除全部映象

docker rmi 映象id
# -q獲取映象的id
docker rmi $(docker images -q)
docker rmi `docker images -q`

5.建立本地映象

找到你需要構建映象的Dockerfile檔案的目錄位置,cd進去

# -t 映象名稱 .是在指定映象構建過程中的上下文環境的目錄,並非指的本地目錄
# -f ./dockerfile(dockerfile的路徑)
docker build -t myimage .

這裡的"."想要理解的,需要了解一下映象構建上下文(Context),參考地址:如何理解docker映象build中的上下文 - 初級程式設計 - 部落格園 (cnblogs.com)

6.將容器提交為映象

映象是多層儲存,每一層是在前一層的基礎上進行的修改;而容器同樣也是多層儲存,是在以映象為基礎層,在其基礎上加一層作為容器執行時的儲存層。

當我們需要通過一個基礎映象做開發,開發完希望打包成一個映象以後複用時,我們可以先根據該映象啟動容器,做行為操作後再將容器提交為映象。

# docker commit -a="作者" -m="訊息" 容器id or name 新映象名稱
docker commit -a="test@163.com" -m="test commit" a404c6c174a2 tomcat_test:1.0

7.標記本地映象或歸入某一倉庫

docker tag : 可標記本地映象,可將其歸入某一倉庫。

語法:docker tag [OPTIONS] IMAGE[:TAG] [REGISTRYHOST/][USERNAME/]NAME[:TAG]

# 例:歸入某一倉庫       docker使用者id/倉庫(沒有該倉庫則預設建立)
docker tag mynginx:v1 hyx1229/mynginx
# 例:打個標記
docker tag myningx:v1 myningx-v2:v2

8.將映象打包成壓縮包

# -o 資料夾目錄必須存在,最後為檔名
docker save -o ./test/app myimages

9.將壓縮包還原成映象

# -i 指定tar壓縮包
docker load	-i ./test/app

二、容器操作

1.檢視執行的容器

docker ps
# 檢視全部容器
docker ps -a

2.建立並執行容器

# i保持容器執行 t為容器分配一個偽終端   name後面是容器名稱    -it預設進入容器,退出容器,容器也會停止執行
docker run -it --name=container01 redis
# d容器在後臺執行 需要使用docker exec container02進入容器 容器不會關閉
docker run -id --name=container02 redis
# -it建立的容器一般稱為互動式容器 -id建立的容器一般稱為守護式容器

#                         宿主機埠號:容器內部暴露的埠號
docker run -id --name=container03 -p 8088:80 myimage

docker run幹了什麼

image

3.進入容器

# 進入容器後開啟一個新的終端,可以在裡面操作(常用)
docker exec -it 容器名or容器id bash
# 進入容器正在執行的終端,不會啟動新的程式
docker attach xxx

4.啟動容器

docker start 容器名or容器id
# 重啟容器
docker restart 容器名or容器id

5.停止容器

docker stop 容器名or容器id
# 停止正在執行的全部容器
docker stop $(docker ps -q)

6.刪除容器、刪除全部容器

docker rm 容器名or容器id
# 刪除全部容器 -f 強制刪除
docker rm -f $(docker ps -aq)

7.檢視容器資訊或映象資訊

docker inspect 容器名or容器id | 映象id

8.檢視容器日誌

可以通過檢視日誌,得到容器啟動失敗或一些錯誤資訊、原因

docker logs 容器名

9.檢視容器中的程式資訊

docker top 容器名or容器id

10.從容器內拷貝檔案到主機上

#             容器內部路徑      宿主機路徑
docker cp 容器:/home/test.txt /home

11.容器重新命名

docker rename container_name new_name

四、資料卷

1.資料卷的概念

為什麼要有資料卷這個東西呢,因為使用容器有存在一些問題,例如:

場景:一個mysql的容器裡面有很多資料庫,突然容器執行不起來了,只能刪除這個容器通過映象重新執行一個,容器刪除了,容器中的資料也隨之銷燬,資料我們只能重新建立,這是很頭疼的,也是我們不希望發生的。因此產生三個問題:

1.docker容器刪除後,在容器中產生的資料如何儲存備份?

2.docker容器和外部機器可以直接交換檔案嗎?

3.容器之間如何資料互動?

資料卷為什麼可以解決這些問題:

  • 資料卷是宿主機(例如:你的虛擬機器linux伺服器)中的一個目錄或檔案
  • 當容器目錄和資料卷目錄繫結後,對方的修改會立即同步
  • 一個資料卷可以被多個容器同時掛載
  • 一個容器也可以掛載多個資料卷

2.資料卷的作用

資料卷是被設計用來持久化資料的,它的生命週期獨立於容器,Docker不會在容器被刪除後自動刪除資料卷,並且也不存在垃圾回收這樣的機制來處理沒有任何容器引用的資料卷。

  • 容器資料持久化
  • 外部機器(你的window)和容器間接通訊
  • 容器之間資料互動
  • image

3.配置資料卷

建立啟動容器時,使用 -v 引數 設定資料卷

docker run containerName -v 宿主機目錄(檔案):容器內目錄(檔案)

注意:

  • 目錄必須是絕對路徑

  • 目錄不存在會自動建立

  • 可以掛載多個資料卷,多個-v。例如:

  • docker run -it --name=c1 -v /xhnbzdl/docker_data:/container_data/d1 -v /xhnbzdl/vueDemo:/container_data/d2 redis
    
  • 掛載繫結時無法重複繫結容器的某一個目錄,例如:

  • # 使用了兩個/container_data/d1,會報錯
    docker run -it --name=c2 -v /xhnbzdl/docker_data:/container_data/d1 -v /xhnbzdl/vueDemo:/container_data/d1 redis
    
  • 但宿主機的目錄可以重複繫結在容器內的不同路徑下,例如:

  • docker run -it --name=c2 -v /xhnbzdl/docker_data:/container_data/d1 -v /xhnbzdl/docker_data:/container_data/d2 redis
    

檢視資料卷掛載

docker inspect 容器name

image

4.容器資料卷

多容器進行資料共享:

  1. 方式一:多個容器掛載同一個資料卷

  2. 方式二:容器資料卷:容器c1繫結資料卷,其他的容器繫結容器c1

  3. image

命令:

# c1作為容器資料卷,不用在宿主建立目錄,建立容器時會自動建立(匿名掛載)
docker run -it --name=c1 -v /volume_data redis
# 建立啟動c2,c3容器,使用--volumes-form引數 設定資料卷
docker run -it --name=c2 --volumes-from c1 redis
docker run -it --name=c3 --volumes-from c1 redis
  1. 使用--volumes-from啟動的容器得到的資料卷可以理解為拷貝模式的,比如c2,c3是複製了c1的資料卷,因此如果c1容器刪除了,並不會影響c2和c3,資料會依然存在。

5.匿名掛載和具名掛載

1.匿名掛載

該命令下-v指的是容器內的路徑,宿主機路徑不填代表匿名掛載,將由系統分配,-P注意是大寫

# -P隨機分配埠(大寫)                  匿名掛載
docker run -d -P --name c_nginx -v /etc/nginx nginx 

檢視docker掛載的資料卷情況

docker volume ls

image

這些隨機生成的字串就是匿名掛載的,那麼怎麼檢視這些匿名掛載的資料卷所在的位置呢,如下:

# docker inspect 資料卷的name
docker inspect  00c39969fe0c89841f47b2efe54f32ad79ba75e43c17b51268cb01715da17666

注意:Mountpoint就是資料卷在宿主機的位置,所有未指定目錄的卷都在/var/lib/docker/volumes/xxxx/_data目錄下。
image

2.具名掛載

大多數情況我們都使用具名掛載

該命令下-v後面的第一個引數只是一個名字,不是路徑,如果帶有/就代表路徑了

docker run -d -p 81:80 --name c_nginx02 -v hasname:/etc/nginx nginx 

再檢視全部資料卷docker volume ls

image

這個hasname就是具名掛載的,可以再檢視實際掛載的位置docker insepct hasname

image

3.刪除資料卷

容器正在使用的資料卷不能刪除,繫結掛載的無法刪除。

# docker volume rm 資料卷name
docker volume rm hasname

4.建立資料卷

建立一個資料卷

docker volume create --name=test

5.擴充套件

通過 -v 容器內路徑:ro 、rw 改變讀寫許可權

ro readonly #只讀
rw readwrite #可讀可寫

# 容器內只讀,無法新增檔案或修改檔案操作,只能從宿主機來操作
docker run -d -P --name c_nginx03 -v hasname-nginx:/etc/nginx:ro  nginx
# 容器內可讀寫操作
docker run -d -P --name c_nginx03 -v hasname-nginx:/etc/nginx:rw  nginx

資料卷命令彙總

命令 描述
docker volume create 建立一個卷
docker volume inspect 顯示一個或多個卷的詳細資訊
docker volume ls 列出卷
docker volume prune 刪除所有未使用的卷
docker volume rm 刪除一個或多個卷

五、實戰部署

1.Docker部署MySql

1、搜尋mysql映象

docker search mysql

2、拉取映象

docker pull mysql:8.0

3.建立容器、設定埠對映和資料卷掛載

# 宿主機建立用於存放mysql資料的資料卷目錄
mkdir /root/mysql
cd /root/mysql
# $PWD 代表當前路徑(只能是大寫的PWD),我是先cd到/root/mysql路徑的,$PWD==/root/mysql
# -e 設定環境變數
docker run -id \
-p 3306:3306 \
--name=c_mysql \
-v $PWD/conf:/ect/mysql/conf.d \
-v $PWD/logs:/logs \
-v $PWD/data:/var/lib/mysql \
-e MYSQL_ROOT_PASSWORD=123456 \
mysql:8.0

4.注意的點:

執行命令前保證當前所在的目錄正確,否則下次會找不到資料卷。

關於資料卷,在/root/mysql中會生成三個資料夾,data中會存放建立的資料庫。值得注意的地方是,我在測試資料卷共享資料時,我另外起了一個容器c_mysql2,埠3307:3306,然後同樣繫結上面路徑的資料卷並且執行成功,但是用navicat卻無法連線上,報錯:

image

並且進入容器c_mysql2進入/var/lib/mysql,通過建立檔案發現我在容器之間的檔案的確是共享了的,這可能是與mysql的執行有關。因此只需要將其中一個容器停止執行就可以正常訪問並且同步資料了。

2.Docker部署Nginx

1.搜尋映象

docker search nginx

2.拉取映象

docker pull nginx

3.建立容器,設定埠對映、資料卷對映

# 宿主機建立用於存放mysql資料的資料卷目錄
mkdir /root/nginx
cd /root/nginx

注意:部署nginx時需要提前寫好nginx.conf這個檔案

mkdir conf
cd conf
# 建立nginx的配置檔案
vim nginx.conf

貼上以下內容:

這個是刪除註釋後的nginx的預設配置,複製完nginx.conf後記得cd .. 回到/root/nginx目錄

worker_processes  1;

events {
    worker_connections  1024;
}


http {
    include       mime.types;
    default_type  application/octet-stream;
    sendfile        on;

    keepalive_timeout  65;


    server {
        listen       80;
        server_name  localhost;
        location / {
            root   html;
            index  index.html index.htm;
        }

        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }

    }
}

建立前記得檢查埠是否被佔用,這裡我的80埠被佔用了所以用81

埠占用解決辦法:

# 1.查詢被佔用的埠
netstat -tln  
netstat -tln | grep 80
# 2.檢視埠屬於哪個程式?埠被哪個程式佔用
lsof -i :80
# 3.殺掉佔用埠的程式
kill -9 程式id 

建立執行容器

docker run -id --name=c_nginx \
-p 81:80 \
-v $PWD/conf/nginx.conf:/etc/nginx/nginx.conf \
-v $PWD/logs:/var/log/nginx \
-v $PWD/app:/usr/share/nginx/app \
nginx

4.外部機器訪問容器 ip:埠

image

3.Docker部署redis

1.直接拉取映象

docker pull redis

2.建立執行容器

前置:建立資料卷資料夾

mkdir /root/redis
cd /root/redis

提前寫好配置檔案

mkdir conf
cd conf
vim redis.conf

複製以下程式碼,redis的預設配置,配置需要稍作修改

注意:

在docker中啟動redis一定要把:daemonize 設定為 no,這個很重要,如果不是no, docker會一直啟動失敗,原因是docker本身需要後臺執行,而這個配置選項也是以守護程式啟動,兩者會衝突。

資料持久化:appendonly可以設定為no,那麼docker命令啟動時則需要加上--appendonly yes。

密碼驗證:requirepass可以用預設的,預設是沒有密碼驗證,如果需要則在配置中加上 requirepass 123456

不加則可以在docker命令中加引數--requirepass “123456"

# bind 只設定為0.0.0.0 將不能遠端連線
# bind 0.0.0.0

# protected-mode 設定為no,關閉保護模式
protected-mode no

port 6379


tcp-backlog 511


timeout 0

tcp-keepalive 300

# 後臺執行
daemonize no

supervised no

pidfile /var/run/redis_6379.pid

loglevel notice

logfile ""

databases 16

always-show-logo yes

save 900 1
save 300 10
save 60 10000

stop-writes-on-bgsave-error yes

rdbcompression yes

rdbchecksum yes

dbfilename dump.rdb

dir ./


replica-serve-stale-data yes

replica-read-only yes

repl-diskless-sync no

repl-diskless-sync-delay 5

repl-disable-tcp-nodelay no

replica-priority 100

lazyfree-lazy-eviction no
lazyfree-lazy-expire no
lazyfree-lazy-server-del no
replica-lazy-flush no
# 是否開啟資料持久化,開啟則會將資料寫入硬碟
appendonly no

appendfilename "appendonly.aof"

appendfsync everysec

no-appendfsync-on-rewrite no

auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb

aof-load-truncated yes

aof-use-rdb-preamble yes

lua-time-limit 5000

slowlog-log-slower-than 10000

slowlog-max-len 128

latency-monitor-threshold 0

notify-keyspace-events ""

hash-max-ziplist-entries 512
hash-max-ziplist-value 64

list-max-ziplist-size -2

list-compress-depth 0

set-max-intset-entries 512

zset-max-ziplist-entries 128
zset-max-ziplist-value 64

hll-sparse-max-bytes 3000

stream-node-max-bytes 4096
stream-node-max-entries 100

activerehashing yes

client-output-buffer-limit normal 0 0 0
client-output-buffer-limit replica 256mb 64mb 60
client-output-buffer-limit pubsub 32mb 8mb 60

hz 10

dynamic-hz yes

aof-rewrite-incremental-fsync yes

rdb-save-incremental-fsync yes
requirepass 123456

執行容器

# cd 到/root/redis
cd ..

指定配置檔案啟動redis

docker run -id -p 6379:6379 --name=c_redis \
-v $PWD/conf/redis.conf:/etc/redis/redis.conf \
-v $PWD/data:/data \
-v $PWD/logs:/logs \
redis:latest redis-server /etc/redis/redis.conf 
## 可選引數 --appendonly yes --requirepass "bbb123456"

4.Docker部署MSSQL

1.拉取映象

docker pull mcr.microsoft.com/mssql/server

注意:

這邊掛載資料卷有個大坑,如果直接執行以下命令你大概會得到這樣的錯誤資訊

image

經過一番搜尋得到的結果大概是許可權問題,我在github上所得到的解決方案是

# 那麼我們需要先建立資料卷的路徑,再設定
chown 10001:0 [the-path-of-the-mounted-volume](資料卷的路徑)

2.建立執行容器

docker run -id --name=c_mssql -e 'ACCEPT_EULA=Y' \
-e 'MSSQL_SA_PASSWORD=Xhnbzdl0114' \
-p 1433:1433 \
-v /root/docker_data/mssql:/var/opt/mssql \
mcr.microsoft.com/mssql/server

六、Dockerfile常用關鍵字

1.FORM

格式為 FROM <image>FROM <image>:<tag>

第一條指令必須為 FROM 指令。並且,如果在同一個Dockerfile中建立多個映象時,可以使用多個 FROM 指令(每個映象一次)。

2.MAINTAINER

格式為 MAINTAINER <name>,指定維護者資訊。以棄用。

3.RUN

格式為 RUN <command>RUN ["executable", "param1", "param2"]

例如: RUN ["dotnet", "resotre", "YXChatApiService/YXChatApiService.csproj"]

前者將在 shell 終端中執行命令,即 /bin/sh -c;後者則使用 exec 執行。指定使用其它終端可以通過第二種方式實現,例如 RUN ["/bin/bash", "-c", "echo hello"]

每條 RUN 指令將在當前映象基礎上執行指定命令,並提交為新的映象。當命令較長時可以使用 \ 來換行。

4.CMD

支援三種格式

  • CMD ["executable","param1","param2"] 使用 exec 執行,推薦方式;
  • CMD command param1 param2/bin/sh 中執行,提供給需要互動的應用;
  • CMD ["param1","param2"] 提供給 ENTRYPOINT 的預設引數;

指定啟動容器時執行的命令,每個 Dockerfile 只能有一條 CMD 命令。如果指定了多條命令,只有最後一條會被執行。

如果使用者啟動容器時候指定了執行的命令,則會覆蓋掉 CMD 指定的命令。

5.EXPOSE

格式為 EXPOSE <port> [<port>...]

告訴 Docker 服務端容器暴露的埠號,供互聯絡統使用。在啟動容器時需要通過 -P,Docker 主機會自動分配一個埠轉發到指定的埠。

6.ENV

格式為 ENV <key> <value>。 指定一個環境變數,會被後續 RUN 指令使用,並在容器執行時保持。

7.ADD

格式為 ADD <src> <dest>

該命令將複製指定的 <src> 到容器中的 <dest>。 其中 <src> 可以是Dockerfile所在目錄的一個相對路徑;也可以是一個 URL;還可以是一個 tar 檔案(自動解壓為目錄)。

8.COPY

格式為 COPY <src> <dest>

複製本地主機的 <src>(為 Dockerfile 所在目錄的相對路徑)到容器中的 <dest>

當使用本地目錄為源目錄時,推薦使用 COPY

9.ENTRYPOINT

兩種格式:

  • ENTRYPOINT ["executable", "param1", "param2"]
  • ENTRYPOINT command param1 param2(shell中執行)。

配置容器啟動後執行的命令,並且不可被 docker run 提供的引數覆蓋。

每個 Dockerfile 中只能有一個 ENTRYPOINT,當指定多個時,只有最後一個起效。

在寫Dockerfile時, ENTRYPOINT或者CMD命令會自動覆蓋之前的ENTRYPOINT或者CMD命令.

10.VOLUME

格式為 VOLUME ["/data"]

多個為VOLUME ["/data","/data2"]

建立一個可以從本地主機或其他容器掛載的掛載點,一般用來存放資料庫和需要保持的資料等。可以預防啟動容器時沒有使用-v設定資料卷

注意:這裡實際上是使用的匿名掛載,他會在宿主機的/var/lib/docker/volumes/xxxx/_data生成這樣一個目錄,xxxx是隨機字串

11.WORKDIR

格式為 WORKDIR /path/to/workdir

為後續的 RUNCMDENTRYPOINT 指令配置工作目錄。

可以使用多個 WORKDIR 指令,後續命令如果引數是相對路徑,則會基於之前命令指定的路徑

12.LABEL

格式為:LABEL <key>=<value> <key>=<value>

取代了MAINTAINER,將後設資料新增到映象

完整示例:

該示例為.net core3.1 WebApi專案,在vs中點選新增docker支援,自動生成的dockerfile檔案。這個檔案有點坑,執行docker build 前記得把dockerfile移動到專案的上一級目錄。

注意:檔案中的每一步,就是映象中的一層。該檔案用到了多構建階段。

#See https://aka.ms/containerfastmode to understand how Visual Studio uses this Dockerfile to build your images for faster debugging.
# 拉取基礎映象,.net的可以是sdk或runtime as 別名 當前映象有執行時
FROM mcr.microsoft.com/dotnet/core/aspnet:3.1-buster-slim AS base
# 容器內部:設定工作目錄,網上說可以理解為cd,如果沒有該目錄則會自動建立
WORKDIR /app
# 暴露的埠
EXPOSE 80

FROM mcr.microsoft.com/dotnet/core/sdk:3.1-buster AS build
WORKDIR /src
#            上下文中的路徑                              容器路徑,預設會建立目錄     /src/YXChatApiService/
COPY ["YXChatApiService/YXChatApiService.csproj", "YXChatApiService/"]
# 執行linux命令 還原nuget包
RUN dotnet restore "YXChatApiService/YXChatApiService.csproj"
# 拷貝上下文中當前目錄下的所有檔案到/src下
COPY . .
WORKDIR "/src/YXChatApiService"
# 執行編譯專案
RUN dotnet build "YXChatApiService.csproj" -c Release -o /app/build
# 基於某一個映象
FROM build AS publish
# 執行釋出命令
RUN dotnet publish "YXChatApiService.csproj" -c Release -o /app/publish
# 基於第一層映象
FROM base AS final
WORKDIR /app
# 從第三層映象中的/app/publish下拷貝,到/app目錄下
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "YXChatApiService.dll"]

我們部署.net的專案時,不想直接將原始碼打包成映象,因為那樣需要下載sdk等映象,如果我們希望將編譯打包後的專案去打包映象,可以修改dockefile為,這樣可以dockerfile和打包後的程式碼放在一個目錄下。

FROM mcr.microsoft.com/dotnet/core/aspnet:3.1
EXPOSE 80
WORKDIR /app
COPY . .
ENTRYPOINT [ "dotnet","YXChatApiService.dll" ]

將Dockerfile檔案放到專案釋出後的目錄下,如:bin\Release\netcoreapp3.1\publish下,然後將publish檔案上傳到伺服器執行docker build打包成映象

七、視覺化皮膚

1.安裝portainer工具

# 這裡-v必填,因為portainer需要根據這個檔案獲取資訊,地址也是固定寫法
# --restart=always重啟docker時,自動啟動相關容器。
docker run -id -p 9000:9000 --name=c_portainer \
--restart=always -v /var/run/docker.sock:/var/run/docker.sock \
--privileged=true portainer/portainer

2.外部訪問ip+埠

image

設定賬號密碼後選擇本地

image

進入portainer的後臺管理介面

image

學習還是推薦使用命令吧,熟能生巧。

八、釋出映象

一、釋出到Docker官網

  1. docker官網註冊自己的賬號

  2. 登入docker賬號

    # 回車,再輸入密碼
    docker login -u username
    # 登入成功會看到Login Succeeded字樣
    
  3. 準備好一個映象,可以是自己寫Dockerfile,也可以直接拉取一個官方映象,我這裡是自己寫的

    [root@iZuf6duvi53ezd1bh557idZ ~]# docker images
    REPOSITORY        TAG       IMAGE ID       CREATED          SIZE
    myjexus           v1        d48ec919287d   12 minutes ago   171MB
    

    執行命令docker push myjexus,如果報錯如下:

    denied: requested access to the resource is denied
    

    先檢查是否登入成功,如果是登入成功的狀態,那麼應該將映象改到自己的賬戶下,方法如下:

    docker tag myjexus:v1 hyx1229/myjexus
    # 再檢視映象
    [root@iZuf6duvi53ezd1bh557idZ ~]# docker images
    REPOSITORY        TAG       IMAGE ID       CREATED          SIZE
    hyx1229/myjexus   latest    d48ec919287d   12 minutes ago   171MB
    myjexus           v1        d48ec919287d   12 minutes ago   171MB
    

    然後釋出新的映象

     docker push hyx1229/myjexus
     # 如下就是釋出成功了,然後就可以登入官網去檢視自己賬戶下的映象了
     [root@iZuf6duvi53ezd1bh557idZ ~]# docker push hyx1229/myjexus
    Using default tag: latest
    The push refers to repository [docker.io/hyx1229/myjexus]
    db12771375e6: Pushed 
    c47aebff94f4: Pushed 
    4fe026c953ab: Pushed 
    42755cf4ee95: Pushed 
    latest: digest: sha256:a378d3cad75ce39772f5f0a63e13d3b60a973ae60e19c7ba1539c585a4e38bf5 size: 1155
    

二、釋出阿里雲

1.準備工作:

  • 登入阿里雲,找到容器映象服務,建立個人例項
  • 建立名稱空間(通常一個大專案為一個)
  • 建立映象倉庫(選本地倉庫即可)

2.操作和釋出到官網差不多,進入到倉庫後有詳細的命令說明,如下:

image

九、Docker網路

這部分簡單瞭解一下吧,寫的也不是很詳細,要詳細瞭解的話還是多看看資料吧!

1.容器之間通訊

場景:我們用容器部署了一個專案,同時用容器部署了mssql,那麼專案中的資料庫連線地址我們應該怎麼填?

  • 可以填宿主機的公網ip(不推薦)

  • 可以填Docker0的IP,在宿主機下通過命令ip addr可以檢視到Docker0的ip地址

    Docker0:是安裝Docker後,預設建立的,通常為172.17.0.1,Docker0使用的是橋接模式(Bridge ),使用的是veth-pair技術

    通過docker run啟動的容器在沒有指定網路的情況下,預設是通過Docker0分配的。

  • 可以填容器的ip(容器啟動的ip是不固定的,不推薦)

    檢視容器的ip通過docker inspect 容器id,如下:可以看到Gateway的地址是Docker0的ip,“IPAddress”就是容器的ip

    "Networks": {
        "bridge": {
            "IPAMConfig": null,
            "Links": null,
            "Aliases": null,
            "NetworkID": "ef45d57e9dccf292414db59a2eb6c4c4f7f4a8a3381d42a2647d240a20d2d283",
            "EndpointID": "8333be2f4597db117f562e20b17016647d212ac4afd164c3709f12e4cb2094cd",
            "Gateway": "172.17.0.1",
            "IPAddress": "172.17.0.3",
            "IPPrefixLen": 16,
            "IPv6Gateway": "",
            "GlobalIPv6Address": "",
            "GlobalIPv6PrefixLen": 0,
            "MacAddress": "02:42:ac:11:00:03",
            "DriverOpts": null
        }
    }
    
  • 通過容器名,使用自定義網路或--link

除了通過上面寫ip的方式,我們還可以在docker run的時候使用--link引數指定與某個容器的ip進行互通,如下:

docker run -id -P --name=c_nginx nginx
docker run -id -P --name=c_myjexus --link c_nginx hyx1229/myjexus

這樣我們就可以在容器c_myjexus中ping通我們的c_nginx,並且我們不需要知道c_nginx這個容的ip是多少,可以直接通過容器名ping通,測試:

 docker exec -it c_myjexus ping c_nginx

原理:--link做了什麼

我們檢視容器c_myjexus的host檔案,docker exec -it c_myjexus cat /etc/hosts,如下:

[root@iZuf6gwluazepf3stdxaj3Z ~]# docker exec -it c_myjexus cat /etc/hosts
127.0.0.1       localhost
::1     localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
172.17.0.2      c_nginx 15643c0c776f
172.17.0.3      31a765e18cb3

他將c_nginx的ip追加到了hosts的配置中,並且起了別名,那麼反向c_nginx去ping我們的c_myjexus能通嗎?不能,因為沒有配置,只能通過ip去ping。


為什麼說他過時了呢?

因為--link使用的是docker0,因此實際上預設情況下所有容器都是可以互聯的,沒有隔離,當然這樣安全性不好。使用 --link 就很可能還在用預設橋接網路,這很不安全,所有容器都沒有適度隔離,用自定義網路才比較方便互聯隔離。其次,修改 /etc/hosts 檔案有很多弊病。比如,高頻繁的容器啟停環境時,容易產生競爭冒險,導致 /etc/hosts 檔案損壞,出現訪問故障;或者有些應用發現是來自於 /etc/hosts 檔案後,就假定其為靜態檔案,而快取結果不再查詢,從而導致容器啟停 IP 變更後,使用舊的條目而無法連線到正確的容器等等。

3.自定義網路

列出所有網路docker network ls,這三個是docker安裝時預設建立的

[root@iZuf6gwluazepf3stdxaj3Z ~]# docker network ls
NETWORK ID     NAME      DRIVER    SCOPE
c95d126279ef   bridge    bridge    local
d19e328067c2   host      host      local
e58fb4259b10   none      null      local

有以下幾種網路模式:

  • bridge:橋接(docker預設)
  • none:不配置網路
  • host:和宿主機共享網路
  • container:容器網路連通(用的很少,不建議使用,侷限性很大)

我們自己建立網路,也是用bridge橋接模式。

容器使用自定義網路

  1. 建立自定義的網橋網路

    可以指定子網、IP 地址範圍、閘道器和其他選項。有關詳細資訊,請參閱 Docker 網路建立參考或輸出。docker network create --help

    docker network create --driver bridge --subnet 192.168.0.0/16 --gateway 192.168.0.1 my-net
    
  2. 將容器連線到使用者定義的網橋

    docker run -P --name c_myjexus  \
    --network my-net \
    hyx1229/myjexus
    

    要將正在執行的容器連線到現有的使用者定義網橋

    docker network connect my-net c_nginx
    

    此時c_myjexus和c_nginx就可以通過容器名ping通了

  3. 斷開容器與網橋的連線

    docker network disconnect my-net c_nginx
    

    斷開連線後,容器的網路會重新使用Docker0

  4. 刪除自定義的網橋網路。如果容器當前已連線到網路,請先斷開它們的連線。如:

    # 斷開容器與網橋網路的連線
    docker network disconnect my-net c_myjexus
    # 刪除網橋網路
    docker network rm my-net
    
  5. 檢視網橋下的容器

    docker network inspect my-net
    # 可以看到以下內容
    "Containers": {
        "632e11b4d57fa658e2a4ad7d78f4cf504f275d5511a5fecfae76122b74b06940": {
            "Name": "c_myjexus",
            "EndpointID": "011b3a76ada13aa038fa45030f11c73439f4ca020f5e967e55d2a79c5d73061a",
            "MacAddress": "02:42:c0:a8:00:02",
            "IPv4Address": "192.168.0.2/16",
            "IPv6Address": ""
        },
        "da534f7ca8caf3535a58529216b4be15f4cc8068fb81f31514e0d7050db44bf1": {
            "Name": "c2",
            "EndpointID": "83cd91251b42e553206714c92ae5a7e7395edade69a23d986c05b60b975f41f8",
            "MacAddress": "02:42:c0:a8:00:04",
            "IPv4Address": "192.168.0.4/16",
            "IPv6Address": ""
        }
    }
    

上面我們通過自定義網路,啟動了一個c_myjexus,這時我們再啟動一個c2

docker run -P --name c2  \
--network my-net \
hyx1229/myjexus

此時測試c_myjexus和c2使用的是同一個網橋網路,我們可以測試ping,兩個容器都可以互相使用容器名ping通

[root@iZuf6gwluazepf3stdxaj3Z ~]# docker exec -it c_myjexus ping c2
PING c2 (192.168.0.4): 56 data bytes
64 bytes from 192.168.0.4: icmp_seq=0 ttl=64 time=0.112 ms
64 bytes from 192.168.0.4: icmp_seq=1 ttl=64 time=0.092 ms

[root@iZuf6gwluazepf3stdxaj3Z ~]# docker exec -it c2 ping c_myjexus
PING c_myjexus (192.168.0.2): 56 data bytes
64 bytes from 192.168.0.2: icmp_seq=0 ttl=64 time=0.081 ms
64 bytes from 192.168.0.2: icmp_seq=1 ttl=64 time=0.105 ms

那麼使用自定義網路的容器是否可以ping通docker0起的容器呢?答案是不可以

[root@iZuf6gwluazepf3stdxaj3Z ~]# docker exec -it c2 ping c_nginx
ping: unknown host

那麼如何讓他們之間互通呢,也是通過docker network connect my-net c_nginx命令。執行命令後我們檢視該容器docker insepct c_nginx

發現它擁有兩個網橋,此時就可以互通了,一個容器兩個ip

"Networks": {
    "bridge": {
        "IPAMConfig": null,
        "Links": null,
        "Aliases": null,
        "NetworkID": "c95d126279ef720cf8f1d02ee1a80a7a2a2d66927897299f3ef853572517a88b",
        "EndpointID": "ad2cc6e304f81aa5f1060c3618654cd78631cad1f2a5473f2bdf4d5b62af4d04",
        "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
    },
    "my-net": {
        "IPAMConfig": {},
        "Links": null,
        "Aliases": [
            "15643c0c776f"
        ],
        "NetworkID": "01fee2be9ef852fc48c619ba6d5a6319e7782dcf6ab5bc4722e47814c6e66fe2",
        "EndpointID": "76f2705bdc419e657f2844be7e796c8879223e63aabbb8a9958171c07a79300c",
        "Gateway": "192.168.0.1",
        "IPAddress": "192.168.0.3",
        "IPPrefixLen": 16,
        "IPv6Gateway": "",
        "GlobalIPv6Address": "",
        "GlobalIPv6PrefixLen": 0,
        "MacAddress": "02:42:c0:a8:00:03",
        "DriverOpts": {}
    }
}

注:那麼使用自定義網路和使用Docker0的區別就顯而易見,比如使用自定義網路容器之間可以直接通過容器名ping通。

比如我有一個redis的叢集,就可以打一個網路。還有一個mssql的叢集,也可以搭一個網路。網路之間是互相隔離的。不同叢集使用不同網路,叢集都是健康的。

有關於docker網路的東西還有很多,這裡只是簡單記錄一下。

瞭解了docker網路之後,應該是入門了docker,接下來就可以學習docker-compose以及docker swarm啦。

結語:

本文是自己學習過程中的一些記錄,部分參考了b站狂神黑馬官方文件、以及各路大佬的部落格。

編寫不易,希望能收穫大家的點贊推薦,謝謝!

版權宣告

本文首發連結為:https://www.cnblogs.com/hyx1229/p/15894421.html

作者:不想只會CURD的猿某人

更多原著文章請參考:https://www.cnblogs.com/hyx1229/

相關文章