Docker 學習教程【面試+工作】
1. 瞭解docker
1.1. 思考
我們之前是如何將項目發佈到Linux服務器的?
大致步驟如下:
1、 安裝jdk
2、 安裝tomcat
3、 將項目war包上傳到tomcat的webapps下
4、 修改配置文件
5、 啓動tomcat
這樣看似沒問題,其實我們想想,發一臺機器還好,這幾步就完成了,如果我們要將這個項目發佈到N多臺機器,那麼我們是否需要在每個機器上都進行相同的步驟,並且要進行環境兼容性的測試。
再來看一個例子,我們現在想部署使用一個成熟的產品,這個產品是用go語言開發的,我該如何部署?go語言運行的環境怎麼裝?這個項目又該如何部署?
還有,一臺linux機器上裝了很多軟件,部署了很多項目,相互之間有干擾怎麼辦?
如果有一項技術,可以解決以上問題或者是更多的問題,是不是很爽? 那就是Docker(容器)技術。
1.2. Docker簡介
官網:https://www.docker.com/ (國內打開比較慢)
1.3. 虛擬化和docker的對比
虛擬化:
docker:
docker的優勢在於可以直接使用主機操作系統的資源進行虛擬化。
1.4. 爲什麼要使用docker?
1.5. 架構
Docker daemon(Docker進程):
Docker進程是部署在linux操作系統上,負責支撐Docker Container的運行以及本地Image的管理。
Docker client:
用戶不直接操作Docker daemon,用戶通過Docker client訪問Docker,Docker client提供pull、run等操作命令。
Docker Image:
Docker 鏡像就是一個只讀的模板。
例如:一個鏡像可以包含一個完整的 ubuntu 操作系統環境,裏面僅安裝了 Apache 或用戶需要的其它應用程序。
鏡像可以用來創建 Docker 容器。
Docker 提供了一個很簡單的機制來創建鏡像或者更新現有的鏡像,用戶甚至可以直接從其他人那裏下載一個已經做好的鏡像來直接使用。
Docker Container:
Docker 利用容器來運行應用。容器是從鏡像創建的運行實例。它可以被啓動、開始、停止、刪除。每個容器都是相互隔離的、保證安全的平臺。可以把容器看做是一個簡易版的 Linux 環境(包括root用戶權限、進程空間、用戶空間和網絡空間等)和運行在其中的應用程序。
Docker Registry:
倉庫分爲公開倉庫(Public)和私有倉庫(Private)兩種形式
最大的公開倉庫是 Docker Hub,存放了數量龐大的鏡像供用戶下載。
用戶也可以在本地網絡內創建一個私有倉庫。
當用戶創建了自己的鏡像之後就可以使用 push 命令將它上傳到公有或者私有倉庫,這樣下次在另外一臺機器上使用這個鏡像時候,只需要從倉庫上 pull 下來就可以了。
2. 安裝docker
我們可以在Centos或者Ubuntu下安裝docker,要注意的是,centos6對docker支持的不好,使用docker建議升級到centos7。
docker官方建議使用Ubuntu系統,兼容性更好一些。所以,我們使用Ubuntu系統來學習docker。
Ubuntu系統的安裝參考《VMware Workstation 中安裝 Ubuntu16.04 虛擬機.docx》
在課前資料中已經提供了“Ubuntu16-64-鏡像”,我們直接導入即可學習,該鏡像中包含安裝了lrzsz、jdk1.8、docker 1.12並且將所有的應用升級到最新。
2.1. centos7
直接通過yum安裝即可:
yum install -y docker
2.2. centos6
rpm -ivh http://dl.Fedoraproject.org/pub/epel/6/x86_64/epel-release-6-8.noarch.rpm
yum install -y docker-io
service docker start
2.3. Ubuntu 16
apt install docker.io -y
3. 鏡像
3.1. 介紹
3.2. 獲取鏡像
獲取鏡像通過命令,docker pull 完成:
案例:獲取Redis 3.0.0的鏡像。
第一步,需要到遠程的倉庫進行搜索:
https://hub.docker.com/
點擊查看詳情,查看tag:
找到我們想要的3.0.0,最新的tag可以用latest標識:
執行命令:
docker pull redis:3.0
通過docker images查看鏡像:
3.3. 鏡像加速
在國內通過docker官方的倉庫進行下載鏡像是比較慢,這個時候就需要使用加速器了。
在國內,阿里雲、163都提供了docker倉庫,但是阿里雲還提供了加速功能。所以,我們選用阿里雲的加速。 163的倉庫地址:https://c.163.com/hub#/m/home/
使用阿里雲器,需要到阿里雲進行註冊,獲取到自己專屬的加速地址,當然也可以使用我的加速地址。(使用加速是無需登錄的,所以可以公用)
第一步,打開阿里雲網站,點擊控制檯:
https://www.aliyun.com/
第二步,進行登錄,如果沒有賬號就先註冊個賬號,登錄成功後會跳轉到控制檯頁面,找到容器服務:
第三步,點擊“鏡像”:
就可以看到有很多的鏡像了:
第四步,點擊右上角的“鏡像倉庫控制檯”,進入後然後點擊“Docker Hub 鏡像站點”:
就可以看到你的專屬加速地址了:
下面是使用加速地址的方法:
我們採用第2種方法:
再獲取鏡像時發現快多了。
搜素鏡像:
https://dev.aliyun.com/search.html
下載rabbitmq的鏡像:
docker pull rabbitmq:3.6.12
下載完成。
3.4. 查詢本地鏡像
使用docker images 可以看到本地的鏡像列表:
3.5. 刪除鏡像
刪除鏡像通過命令docker rmi 鏡像id完成,需要注意的是,刪除鏡像前,要刪除所有使用到該鏡像的容器。
-f參數是強制刪除,如果有正在運行的容器使用了該鏡像,那麼該鏡像是不會真正的刪除的。
3.6. 搜索鏡像
剛剛我們是通過網頁進行搜索,其實用過docker的命令也可以搜索,具體如下:
4. 容器
4.1. 介紹
4.2. 查看容器列表
通過docker ps命令查看正在運行的容器列表,需要查詢所有的容器需要加-a參數:
docker ps
docker ps -a
4.3. 創建容器
通過docker create 命令可以創建一個容器,這僅僅是創建,並沒有啓動容器。
用法:
4.3.1. 案例
案例:創建Redis的容器。
docker create -p 16379:6379 --name redis redis:3.0
查看容器列表:
啓動容器:
docker start 6e #指定容器的id,只要輸入前幾位即可
通過客戶端進行測試:
至此,第一個docker容器就創建並且已經啓動可用了。
4.4. 創建並且運行容器
上面通過docker create創建了容器,然後通過docker start來啓動容器,其實這種做法並不常用。
更常用的是docker run命令,這個命令的意思是創建並且啓動容器。
用法:
4.4.1. 案例
創建並且運行一個redis容器,它的端口是16380。
docker run -p 16380:6379 --name redis2 redis:3.0
發現,這個容器已經創建並且運行,但是,它並沒有在後臺運行,當按下 control + c時,該容器將停止。
爲了讓容器在後臺運行,需要添加參數 -d。
docker run -p 16380:6379 -d --name redis2 redis:3.0
報錯,說redis2這個名字的容器已經存在,需要我們刪除906的容器或者給新容器重命名。我們重命名試試。
docker run -p 16380:6379 -d --name redis3 redis:3.0
已經創建成功。
進行測試:
測試結果顯示,該容器可用。
接下來,我看下當前運行的容器:
可以看到,有3個redis的容器,並且名爲redis2的容器已經退出,並沒有運行。
那麼問題來了,redis2這個容器我不想要了,怎麼刪除?
4.5. 啓動/停止容器
4.5.1. 啓動容器
用法:docker start 容器名或容器id
4.5.2. 停止容器
停止容器有2種方式:
1、 docker stop 容器名或容器id
2、 docker kill 容器名或容器id
4.6. 刪除容器
通過命令docker rm 刪除容器,刪除正在運行的容器添加 -f 參數。
root@itcast:~# docker rm --help
Usage: docker rm [OPTIONS] CONTAINER [CONTAINER...]
Remove one or more containers
Options:
-f, --force Force the removal of a running container (uses SIGKILL)
--help Print usage
-l, --link Remove the specified link
-v, --volumes Remove the volumes associated with the container
案例:
docker rm redis2
刪除名爲redis2的容器。
4.7. 進入容器
有些時候我們需要進入容器內,做一些操作,比如,修改配置文件等。
進入容器,通過命令 docker exec 完成。
案例:進入redis容器,。
docker exec -it redis /bin/bash
control + d 退出容器。
4.8. 查看日誌
通過命令docker logs -f 容器名或id
5. 倉庫
5.1. 阿里雲倉庫
阿里雲既提供了加速功能,也提供了倉庫功能,也就是我們可以將自己的鏡像上傳到阿里雲倉庫。
https://cr.console.aliyun.com/#/imageList
創建命名空間:
創建鏡像:
創建完成後就可以上傳鏡像到該倉庫了。
5.2. 案例:推送redis鏡像到阿里雲倉庫
第一步,在阿里雲倉庫創建redis鏡像庫:
第二步,在docker中進行登錄:
第三步,給鏡像打tag:
docker tag redis:3.0 registry.cn-hangzhou.aliyuncs.com/itcast/redis:3.0
第四步,推送鏡像到阿里雲:
docker push registry.cn-hangzhou.aliyuncs.com/itcast/redis:3.0
第五步,在阿里雲查看:
接下來,將本地倉庫中的redis鏡像刪除,從阿里雲拉取鏡像到本地。
5.3. 案例:推送鏡像到內網私服
內網私服地址:http://192.168.50.33:8081/ 或 https://192.168.50.33:8443/
賬戶:itcast / 123456
倉庫地址:https://192.168.50.33:8443/repository/itcast/ 需要注意的是,倉庫的端口是18443,而不是8443,在創建倉庫時指定。
docker進行推送鏡像時只能使用https協議,所以,我們需要將證書導入到系統。
上傳證書到/tmp下面
cp /tmp/nexus.crt /usr/local/share/ca-certificates
sudo update-ca-certificates
service docker restart
接下來,進行測試:
#使用docker登錄到私服
docker login 192.168.50.33:18443
#打tag
docker tag percona:5.6 192.168.50.33:18443/percona:5.6
#推送鏡像到私服
docker push 192.168.50.33:18443/percona:5.6
6. 數據管理
容器在運行項目時會產生數據,比如運行的mysql容器,那麼一定會有數據的產生,那麼問題來了,數據是保存在容器內部還是保存在外部?
如果將數據保存在內部,那麼也就意味着我們改變了原有鏡像,這種做法是不可取的,因爲在後期的鏡像升級將變得不可能了。
也就是說,運行的鏡像,最好不要改變,如果必須改變的(比如說,修改配置文件等),在改變後記得commit提交打成一個新的鏡像。
顯然,數據是應該保存在容器的外部,也就是說保存在主機上。那麼問題又來了,數據保存在主機上,那麼容器該如何讀取主機中的數據呢?
6.1. 數據卷
在create或者run容器時,可以通過-v參數指定主機的目錄,掛在到容器中的某一個目錄上,這樣,容器就在這個目錄讀寫數據了。從而實現了容器和數據的分離。
6.2. 案例:運行mysql(percona)容器,將mysql的數據放到主機的/data/mysql-data中。
第一步,下載mysql的鏡像:
地址:https://hub.docker.com/_/percona/
docker pull percona:5.6
第二步,創建容器:
解釋:
第三步,啓動容器:
docker start percona
第四步,進行測試:
查看主機的/data/mysql-data:
7. 構建鏡像
前面我們的學習都是直接從倉庫中拉取鏡像,然後創建容器,最後啓動容器來使用的。
在實際開發過程中,倉庫中的容器可能不能完全滿足我們的需求,比如說,我們項目的部署到docker容器,就不能從倉庫中直接拉取鏡像,就需要自己構建鏡像了。
構建鏡像通過編寫Dockerfile配置文件完成。
7.1. Dockerfile文件
Dockerfile是一個文本文件,裏面編寫多條命令,這些命令描述了一個鏡像構建的細節。
先來看個示例:
DockerFile分爲四部分組成:基礎鏡像信、維護者信息、鏡像操作指令和容器啓動時執行的指令。
7.2. 命令詳解(13個命令)
7.2.1. FROM
7.2.2. MAINTAINER
7.2.3. RUN
7.2.4. CMD
7.2.5. EXPOSE
7.2.6. ENV
7.2.7. ADD
7.2.8. COPY
7.2.9. ENTRYPOINT(入口)
7.2.10. VOLUME(掛載)
7.2.11. USER
7.2.12. WORKDIR
7.2.13. ONBUILD
7.3. 實戰:自己構建redis鏡像
編寫Dockerfile如下:
構建命令:
構建完成:
創建容器:
啓動容器:
測試:
將該鏡像上傳到阿里雲:
8. 部署Spring Cloud微服務
8.1. Spring Boot項目的配置文件
由於項目會經歷不同的環境,有開發環境、測試環境、生產環境,每個環境的地址是不同的,所以,需要在每個環境中編寫不同的配置文件,比如:端口、Eureka服務地址等。
Spring Boot項目的配置文件提供的多種方式指定不同環境配置項的方法,這裏介紹一種通過運行參數或者是JVM參數來指定。
在配置文件中這樣配置:
server:
port: ${port:6778} #服務端口
說明:
${} -- 指定這是一個動態的配置文件項,不是固定的內容
port --指運行參數或者JVM參數來替換的變量值
:6778 -- 指如果運行環境中沒有改配置項,就採用該內容
類似的配置如下:
8.1.1. 方式一:通過運行參數指定
設置方式:--參數名=參數值 --參數名=參數值 ……
8.1.2. 方式二:通過JVM參數指定
設置方式:-D參數名=參數值 --D參數名=參數值 ……
8.2. 部署的規劃
由於我們是測試階段,所以先只發布到一臺機器,在多個容器中運行,一個項目運行一個容器。
項目 | 容器名稱 | IP | 容器內部端口 | 主機端口 | 備註 |
itcast-microservice-eureka | eureka-server | 172.16.55.138 | 6868 | 6868 | 註冊中心 |
itcast-microservice-config-server | config-server | 172.16.55.138 | 6869 | 6869 | 配置服務 |
RabbitMQ | RabbitMQ | 172.16.55.138 | 5672/15672 | 5672/15672 | RabbitMQ服務 |
itcast-microservice-item-1 | item-server-1 | 172.16.55.138 | 6870 | 6870 | 商品服務1 |
itcast-microservice-item-2 | item-server-2 | 172.16.55.138 | 6871 | 6871 | 商品服務2 |
itcast-microservice-order-1 | order-server-1 | 172.16.55.138 | 6872 | 6872 | 訂單服務1 |
itcast-microservice-api-gateway-1 | api-gateway-1 | 172.16.55.138 | 6873 | 6873 | 網關服務1 |
8.3. 部署Eureka註冊中心
8.3.1. 修改配置文件
server:
port: 6868 #服務端口
spring:
application:
name: itcast-microservice-eureka #指定服務名
eureka:
client:
registerWithEureka: false #是否將自己註冊到Eureka服務中,本身就是所有無需註冊
fetchRegistry: false #是否從Eureka中獲取註冊信息
server:
enable-self-preservation: true #禁用自我保護模式
security:
basic:
enable: true #開啓基於HTTP basic的認證
user: #配置用戶的賬號信息
name: itcast
password: itcast123
8.3.2. 導入spring boot打包插件
8.3.3. 進行打包
打包完成:
8.3.4. 拉取java鏡像
docker pull java:8
8.3.5. 製作Docker鏡像
首先將itcast-microservice-eureka.jar文件上傳到linux系統中的/tmp/itcast-microservice-eureka目錄。
編寫Dockerfile文件:
app-entrypoint.sh文件:
構建:
docker build -t itcast-microservice-eureka:1.0.0 .
8.3.6. 運行容器
不設置變量:
8.4. 安裝RabbitMQ服務
同樣也是使用容器來運行RabbitMQ。
測試:
使用guest/guest進行登錄:
RabbitMQ安裝完成。
8.5. 部署itcast-microservice-config-server
8.5.1. 修改配置文件
server:
port: ${port:6869} #服務端口
spring:
application:
name: itcasst-microservice-config-server #指定服務名
cloud:
config:
server:
git: #配置git倉庫地址
uri: ${gitUrl:http://172.16.55.138:10080/zhangzhijun/itcast-config-server.git}
#username: zhangzhijun
#password: 123456
rabbitmq: #RabbitMQ相關的配置
host: ${rabbitMQHost:127.0.0.1}
port: ${rabbitMQPort:5672}
username: ${rabbitMQUsername:guest}
password: ${rabbitMQPassword:guest}
eureka:
client:
registerWithEureka: true #是否將自己註冊到Eureka服務中,默認爲true
fetchRegistry: true #是否從Eureka中獲取註冊信息,默認爲true
serviceUrl: #Eureka客戶端與Eureka服務端進行交互的地址
defaultZone: ${eurekaServerUrl:http://itcast:[email protected]:6868/eureka/}
instance:
prefer-ip-address: true #將自己的ip地址註冊到Eureka服務中
ipAddress: ${ipAddress:127.0.0.1}
management:
security:
enabled: false #是否開啓actuator安全認證
8.5.2. 導入spring boot打包插件
8.5.3. 製作Docker鏡像
首先將itcast-microservice-config.jar文件上傳到linux系統中的/tmp/itcast-microservice-config目錄。
編寫Dockerfile文件:
app-entrypoint.sh文件:
構建:
格式化下看的清楚些:
8.5.4. 運行容器
docker create --name config-server -t -p 6869:6869 -e PORT=6869 -e GIT_URL=https://gitee.com/zhijun.zhang/itcast-config-server.git -e RABBITMQ_HOST=172.16.55.138 -e RABBITMQ_PORT=5672 -e RABBITMQ_USERNAME=guest -e RABBITMQ_PASSWORD=guest -e EUREKA_SERVER_URL=http://itcast:[email protected]:6868/eureka/ -e IP_ADDRESS=172.16.55.138 itcast-microservice-config:1.0.0
docker start config-server && docker logs -f config-server
8.6. 部署itcast-microservice-item-1
8.6.1. 修改配置文件
bootstrap.yml:
eureka:
client:
serviceUrl: #Eureka客戶端與Eureka服務端進行交互的地址
defaultZone: ${eurekaServerUrl:http://itcast:[email protected]:6868/eureka/}
spring:
cloud:
config:
name: microservice #對應的配置服務中的應用名稱
#uri: http://127.0.0.1:6869/
profile: dev #對應配置服務中的{profile}
label: master #對應的分支
discovery:
enabled: true #啓用發現服務功能
service-id: itcasst-microservice-config-server #指定服務名稱
rabbitmq: #RabbitMQ相關的配置
host: ${rabbitMQHost:127.0.0.1}
port: ${rabbitMQPort:5672}
username: ${rabbitMQUsername:guest}
password: ${rabbitMQPassword:guest}
application.yml:
server:
port: ${port:6870} #服務端口
spring:
application:
name: itcasst-microservice-item #指定服務名
logging:
level:
org.springframework: INFO
eureka:
client:
registerWithEureka: true #是否將自己註冊到Eureka服務中,默認爲true
fetchRegistry: true #是否從Eureka中獲取註冊信息,默認爲true
serviceUrl: #Eureka客戶端與Eureka服務端進行交互的地址
defaultZone: ${eurekaServerUrl:http://itcast:[email protected]:6868/eureka/}
instance:
prefer-ip-address: true #將自己的ip地址註冊到Eureka服務中
ip-address: ${ipAddress:127.0.0.1}
management:
security:
enabled: false #是否開啓actuator安全認證
8.6.2. 導入spring boot打包插件
8.6.3. 製作Docker鏡像
首先將itcast-microservice-item.jar文件上傳到linux系統中的/tmp/itcast-microservice-item目錄。
編寫Dockerfile文件:
app-entrypoint.sh文件:
構建:
docker build -t itcast-microservice-item:1.0.0 .
8.6.4. 運行容器
docker create --name item-server-1 -t -p 6870:6870 -e PORT=6870 -e RABBITMQ_HOST=172.16.55.138 -e RABBITMQ_PORT=5672 -e RABBITMQ_USERNAME=guest -e RABBITMQ_PASSWORD=guest -e EUREKA_SERVER_URL=http://itcast:[email protected]:6868/eureka/ -e IP_ADDRESS=172.16.55.138 itcast-microservice-item:1.0.0
docker start item-server-1 && docker logs -f item-server-1
8.7. 部署itcast-microservice-item-2
docker create --name item-server-2 -t -p 6871:6871 -e PORT=6871 -e RABBITMQ_HOST=172.16.55.138 -e RABBITMQ_PORT=5672 -e RABBITMQ_USERNAME=guest -e RABBITMQ_PASSWORD=guest -e EUREKA_SERVER_URL=http://itcast:[email protected]:6868/eureka/ -e IP_ADDRESS=172.16.55.138 itcast-microservice-item:1.0.0
docker start item-server-2 && docker logs -f item-server-2
8.8. 部署itcast-microservice-order-1
8.8.1. 修改配置文件
server:
port: ${port:8082} #服務端口
itcast:
item:
url: http://127.0.0.1:8081/item/
spring:
application:
name: itcasst-microservice-order #指定服務名
eureka:
client:
registerWithEureka: false #是否將自己註冊到Eureka服務中,默認爲true
fetchRegistry: true #是否從Eureka中獲取註冊信息,默認爲true
serviceUrl: #Eureka客戶端與Eureka服務端進行交互的地址
defaultZone: ${eurekaServerUrl:http://itcast:[email protected]:6868/eureka/}
itcasst-microservice-item:
ribbon:
NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule
8.8.2. 導入spring boot打包插件
8.8.3. 製作Docker鏡像
首先將itcast-microservice-order.jar文件上傳到linux系統中的/tmp/itcast-microservice-order目錄。
編寫Dockerfile文件:
app-entrypoint.sh文件:
構建:
docker build -t itcast-microservice-order:1.0.0 .
8.8.4. 運行容器
docker create --name order-server-1 -t -p 6872:6872 -e PORT=6872 -e EUREKA_SERVER_URL=http://itcast:[email protected]:6868/eureka/ itcast-microservice-order:1.0.0
docker start order-server-1 && docker logs -f order-server-1
8.9. 部署itcast-microservice-api-gateway-1
8.9.1. 修改配置文件
server:
port: ${port:6873} #服務端口
spring:
application:
name: itcasst-microservice-api-gateway #指定服務名
zuul:
routes:
item-service: #item-service這個名字是任意寫的
path: /item-service/** #配置請求URL的請求規則
#url: http://127.0.0.1:8081 #真正的微服務地址
serviceId: itcasst-microservice-item #指定Eureka註冊中心中的服務id
eureka:
client:
registerWithEureka: true #是否將自己註冊到Eureka服務中,默認爲true
fetchRegistry: true #是否從Eureka中獲取註冊信息,默認爲true
serviceUrl: #Eureka客戶端與Eureka服務端進行交互的地址
defaultZone: ${eurekaServerUrl:http://itcast:[email protected]:6868/eureka/}
instance:
prefer-ip-address: true #將自己的ip地址註冊到Eureka服務中
ip-address: ${ipAddress:127.0.0.1}
8.9.2. 導入spring boot打包插件
8.9.3. 製作Docker鏡像
首先將itcast-microservice-api-gateway.jar文件上傳到linux系統中的/tmp/ itcast-microservice-api-gateway目錄。
編寫Dockerfile文件:
app-entrypoint.sh文件:
構建:
docker build -t itcast-microservice-api-gateway:1.0.0 .
8.9.4. 運行容器
docker create --name api-gateway-1 -t -p 6873:6873 -e PORT=6873 -e IP_ADDRESS=172.16.55.138 -e EUREKA_SERVER_URL=http://itcast:[email protected]:6868/eureka/ itcast-microservice-api-gateway:1.0.0
docker start api-gateway-1 && docker logs -f api-gateway-1
閱讀原文即可在線觀看教程及下載教程