Docker已經上市不少年,不是什麼新鮮事物了,不少企業或者開發同窗之前也很少很多有所接觸,可是有實操經驗的人很少,本系列教程主要偏重實戰,儘可能講乾貨,會根據本人理解去作闡述,具體官方概念能夠查閱官方教程,本章目標以下:css
由於我是Mac用戶,因此這裏VirturalBox和vagrant使用的是Mac版本,你們到官網各自下載對應的系統版本便可,強烈建議使用迅雷下載!html
Vagrant下載mysql
VirtualBox下載linux
簡單來講Docker是一款能夠將應用程序與基礎設施分離、代碼及其全部依賴項打包,使應用程序可以從一個計算環境快速可靠地運行到另外一個計算環境,達到快速交付、測試、部署的容器化技術。web
使用Linux容器部署應用程序稱爲容器化。 sql
咱們能夠反過來思考,不用Docker這些容器化技術會怎麼樣,會遇到什麼問題和瓶頸。docker
想要發佈一個應用到測試、生產環境使用,都會經歷如下流程: shell
物理機時代數據庫
每一個團隊會須要申請一臺物理機做爲測試開發環境,進行一系列的環境搭建 apache
虛擬化時代
在虛擬化技術出現以後,每一個團隊只須要申請一臺虛擬機,多臺虛擬機能夠共享同一臺物理機,大大下降了成本,必定程度上提高了資源利用率,當公司搞活動時系統須要擴展,只須要經過虛擬機鏡像建立多個虛擬機便可,提高了系統擴展性和可用性
從上圖不難發現,主機機器會爲每一個客體機器(虛擬機)提早分配好資源,與物理機時代同樣,實際上應用自己可能並不須要那麼多物理資源,有一部分資源被操做系統所佔用,大部分時候處於閒置狀態,仍然存在一些問題以下:
容器化時代
Docker容器相似沙箱,每一個容器之間相互獨立、資源隔離、互不干擾,Docker容器化技術出現後,基本解決了上面提到的問題,Docker有如下優點:
Docker提供資源隔離機制,利用Linux內核的 namespace機制來作容器之間的隔離,經過內核的 cgroups 機制來作容器的資源限制(CPU、Memory、Disk等)。
可是直接在主體機器安裝Docker,也會致使Docker容器直接依賴主體機器操做系統,沒辦法實現多租戶隔離,後面章節會提到對應解決方案。
鏡像是一個可執行包,包含運行應用程序所需的全部內容——代碼、運行時、庫、環境變量和配置文件。容器是經過運行鏡像啓動容器,是鏡像的運行時實例。鏡像實際上就是一個容器的模板,經過這個模板能夠建立不少相同的容器。
經過Java去類比理解Docker的一些概念:
容器在Linux上本地運行,並與其餘容器共享主機的內核。它運行一個獨立的進程,不佔用比其餘任何可執行程序更多的內存,使其輕量級。
虛擬機(VM) 運行一個成熟的「遊客」操做系統,經過虛擬機監控程序對主機資源進行虛擬訪問。一般,vm提供的資源比大多數應用程序所需的要多。
其實兩款產品沒有什麼可比性,由於使用場景不一樣,這裏列出來主要是避免一些童鞋誤解。
docker是一款用於快速交付、測試、部署的工具,簡化了應用環境的搭建和管理工做。二者適用範圍不一樣。一個容器就是一個包含了應用執行所依賴的數據(包括lib,配置文件等等),Docker能夠經過同一個鏡像文件快速在不一樣的環境(開發、測試、生產)搭建多個相同的容器。
Vagrant是用於管理虛擬機,Docker用於管理應用環境。
Docker引擎是一個客戶端-服務器應用程序,主要組件以下:
Docker架構體系
Docker使用客戶機-服務器架構。
Docker客戶機與Docker守護進程進行對話,後者負責構建、運行和分發Docker容器。
Docker客戶機和守護進程能夠在同一系統上運行,也能夠將Docker客戶機鏈接到遠程Docker守護進程。Docker客戶機和守護進程經過UNIX套接字或網絡接口使用REST API進行通訊。
Docker鏡像是由一系列層構成的。每一層表明鏡像Dockerfile中的一條指令。除了最後一層以外,每一層都是隻讀的。Docker鏡像分層最大的好處是共享資源,其餘相同環境的軟件鏡像都共同去享用同一個環境鏡像,而不須要每一個軟件鏡像要去建立一個底層環境。
上面章節也提到過,若是咱們把Docker直接安裝在主體機器,會致使Docker直接依賴了咱們主體機器的操做系統,若是不一樣的團隊共用一臺物理機時,沒辦法作到每一個團隊或每一個環境都獨享本身的操做系統和相應的權限。 目前通常的部署模式有如下幾種:
當虛擬機太多的時候,咱們也沒辦法手動一個個去管理,所以這裏用到Vagrant工具去管理虛擬機。
以Tomcat容器做爲一個例子,這裏虛擬機網絡模式默認是bridge
方式,在實戰部分也有詳細步驟,應用部署圖以下:
docker run -d --name evan-tomcat -p 9090:8080 tomcat
複製代碼
經過命令查看獲得,主體機器、客體機器、Tomcat容器IP地址(跟圖片一致)以下:
192.168.100.4
192.168.100.9
172.17.0.3
嘗試主體機器(MacOS)訪問客體機器(Centos)
192:~ evan$ ping 192.168.100.9
PING 192.168.100.9 (192.168.100.9): 56 data bytes
64 bytes from 192.168.100.9: icmp_seq=0 ttl=64 time=0.481 ms
64 bytes from 192.168.100.9: icmp_seq=1 ttl=64 time=0.477 ms
64 bytes from 192.168.100.9: icmp_seq=2 ttl=64 time=0.447 ms
64 bytes from 192.168.100.9: icmp_seq=3 ttl=64 time=0.339 ms
64 bytes from 192.168.100.9: icmp_seq=4 ttl=64 time=0.400 ms
64 bytes from 192.168.100.9: icmp_seq=5 ttl=64 time=0.324 ms
複製代碼
能夠看到,主體機器是能夠直接與客體機器進行通訊,由於在同一個網段
嘗試客體機器(Centos)訪問Tomcat容器
[root@10 /]# ping 172.17.0.3
PING 172.17.0.3 (172.17.0.3) 56(84) bytes of data.
64 bytes from 172.17.0.3: icmp_seq=1 ttl=64 time=0.036 ms
64 bytes from 172.17.0.3: icmp_seq=2 ttl=64 time=0.043 ms
64 bytes from 172.17.0.3: icmp_seq=3 ttl=64 time=0.047 ms
64 bytes from 172.17.0.3: icmp_seq=4 ttl=64 time=0.042 ms
複製代碼
在虛擬機上能夠直接與Tomcat容器進行通訊
嘗試主體機器(MacOS)經過客體機器(Centos)端口9090訪問Tomcat容器
192:~ evan$ curl 192.168.100.9:9090
<!doctype html><html lang="en"><head><title>HTTP Status 404 – Not Found</title><style type="text/css">body {font-family:Tahoma,Arial,sans-serif;} h1, h2, h3, b {color:white;background-color:#525D76;} h1 {font-size:22px;} h2 {font-size:16px;} h3 {font-size:14px;} p {font-size:12px;} a {color:black;} .line {height:1px;background-color:#525D76;border:none;}</style></head><body><h1>HTTP Status 404 – Not Found</h1><hr class="line" /><p><b>Type</b> Status Report</p><p><b>Message</b> Not found</p><p><b>Description</b> The origin server did not find a current representation for the target resource or is not willing to disclose that one exists.</p><hr class="line" /><h3>Apache Tomcat/8.5.50</h3></body></html>192:~ evan$
複製代碼
能夠看到主體機器能夠經過客體機器IP+端口方式訪問容器,所以主體機器訪問的並非容器真實的端口,而是虛擬機上端口的映射。
1.建立一個centos7文件夾
mkdir centos7
複製代碼
2.在當前文件夾初始化Vagrantfile
vagrant init centos7
複製代碼
輸出結果以下:
192:centos7 evan$ vagrant init centos7
A `Vagrantfile` has been placed in this directory. You are now
ready to `vagrant up` your first virtual environment! Please read
the comments in the Vagrantfile as well as documentation on
`vagrantup.com` for more information on using Vagrant.
複製代碼
3.進入Vagrantfile,更改配置以下:
# -*- mode: ruby -*-
# vi: set ft=ruby :
# All Vagrant configuration is done below. The "2" in Vagrant.configure
# configures the configuration version (we support older styles for
# backwards compatibility). Please don't change it unless you know what
# you're doing.
Vagrant.configure("2") do |config|
# The most common configuration options are documented and commented below.
# For a complete reference, please see the online documentation at
# https://docs.vagrantup.com.
# Every Vagrant development environment requires a box. You can search for
# boxes at https://vagrantcloud.com/search.
config.vm.box = "centos7"
# Disable automatic box update checking. If you disable this, then
# boxes will only be checked for updates when the user runs
# `vagrant box outdated`. This is not recommended.
# config.vm.box_check_update = false
# Create a forwarded port mapping which allows access to a specific port
# within the machine from a port on the host machine. In the example below,
# accessing "localhost:8080" will access port 80 on the guest machine.
# NOTE: This will enable public access to the opened port
# config.vm.network "forwarded_port", guest: 80, host: 8080
# Create a forwarded port mapping which allows access to a specific port
# within the machine from a port on the host machine and only allow access
# via 127.0.0.1 to disable public access
# config.vm.network "forwarded_port", guest: 80, host: 8080, host_ip: "127.0.0.1"
# Create a private network, which allows host-only access to the machine
# using a specific IP.
# config.vm.network "private_network", ip: "192.168.33.10"
# Create a public network, which generally matched to bridged network.
# Bridged networks make the machine appear as another physical device on
# your network.
config.vm.network "public_network"
# Share an additional folder to the guest VM. The first argument is
# the path on the host to the actual folder. The second argument is
# the path on the guest to mount the folder. And the optional third
# argument is a set of non-required options.
# config.vm.synced_folder "../data", "/vagrant_data"
# Provider-specific configuration so you can fine-tune various
# backing providers for Vagrant. These expose provider-specific options.
# Example for VirtualBox:
#
# config.vm.provider "virtualbox" do |vb|
# # Display the VirtualBox GUI when booting the machine
# vb.gui = true
#
# # Customize the amount of memory on the VM:
# vb.memory = "1024"
# end
config.vm.provider "virtualbox" do |vb|
vb.memory = "4000"
vb.name= "evan-centos7"
vb.cpus= 2
end
#
# View the documentation for the provider you are using for more
# information on available options.
# Enable provisioning with a shell script. Additional provisioners such as
# Puppet, Chef, Ansible, Salt, and Docker are also available. Please see the
# documentation for more information about their specific syntax and use.
# config.vm.provision "shell", inline: <<-SHELL
# apt-get update
# apt-get install -y apache2
# SHELL
end
複製代碼
5.將下載的鏡像文件保存到你係統的一個目錄下,我本機的存放目錄是:
/Users/evan/development/visualbox/virtualbox.box
複製代碼
6.將centos7鏡像文件添加到vagrant管理的鏡像中,並將鏡像命名爲centos7
vagrant box add centos7 /Users/evan/development/visualbox/virtualbox.box
複製代碼
添加成功輸出結果以下:
192:visualbox evan$ vagrant box add centos7 /Users/evan/development/visualbox/virtualbox.box
==> box: Box file was not detected as metadata. Adding it directly...
==> box: Adding box 'centos7' (v0) for provider:
box: Unpacking necessary files from: file:///Users/evan/development/visualbox/virtualbox.box
==> box: Successfully added box 'centos7' (v0) for 'virtualbox'!
複製代碼
7.查看已添加的虛擬機鏡像,可經過vagrant box list
192:visualbox evan$ vagrant box list
centos7 (virtualbox, 0)
複製代碼
能夠看到,已經成功添加centos7
8.根據Vagrantfile文件啓動建立虛擬機,去到剛纔初始化Vagrantfile的文件夾,執行vagrant up
建立虛擬機,vagrant會自動根據咱們在Vagrant配置好的參數來建立虛擬機,注意咱們上面添加的虛擬機名字centos7
要與配置文件中的config.vm.box = "centos7"
一致。(執行過程當中,Virtualbox應用不須要打開)
192:centos7 evan$ vagrant up
Bringing machine 'default' up with 'virtualbox' provider...
==> default: Clearing any previously set forwarded ports...
==> default: Clearing any previously set network interfaces...
==> default: Available bridged network interfaces:
1) en0: Wi-Fi (Wireless)
2) en5: USB Ethernet(?)
3) p2p0
4) awdl0
5) llw0
6) en7: USB 10/100/1000 LAN
7) en1: Thunderbolt 1
8) en2: Thunderbolt 2
9) en3: Thunderbolt 3
10) en4: Thunderbolt 4
11) bridge0
==> default: When choosing an interface, it is usually the one that is
==> default: being used to connect to the internet.
default: Which interface should the network bridge to? 1
==> default: Preparing network interfaces based on configuration...
default: Adapter 1: nat
default: Adapter 2: bridged
==> default: Forwarding ports...
default: 22 (guest) => 2222 (host) (adapter 1)
==> default: Running 'pre-boot' VM customizations...
==> default: Booting VM...
==> default: Waiting for machine to boot. This may take a few minutes...
default: SSH address: 127.0.0.1:2222
default: SSH username: vagrant
default: SSH auth method: private key
default:
default: Vagrant insecure key detected. Vagrant will automatically replace
default: this with a newly generated keypair for better security.
default:
default: Inserting generated public key within guest...
default: Removing insecure key from the guest if it's present... default: Key inserted! Disconnecting and reconnecting using new SSH key... ==> default: Machine booted and ready! ==> default: Checking for guest additions in VM... default: No guest additions were detected on the base box for this VM! Guest default: additions are required for forwarded ports, shared folders, host only default: networking, and more. If SSH fails on this machine, please install default: the guest additions and repackage the box to continue. default: default: This is not an error message; everything may continue to work properly, default: in which case you may ignore this message. ==> default: Configuring and enabling network interfaces... ==> default: Rsyncing folder: /Users/evan/development/centos7/ => /vagrant 複製代碼
執行完畢,能夠打開Visualbox查看是否已經多了一個centos7虛擬機
安裝Docker以前,須要進入剛纔安裝好的Centos7操做系統,所以須要先設置下SSH配置,這裏使用的是帳號密碼登錄
1.使用vagrant ssh
命令進入虛擬機
192:centos7 evan$ vagrant ssh
-bash: warning: setlocale: LC_CTYPE: cannot change locale (UTF-8): No such file or directory
[vagrant@10 ~]$ ls
複製代碼
2.執行sudo -i
命令切換到root用戶,而後進入經過vi /etc/ssh/sshd_config
命令修改SSH安全認證配置
[vagrant@10 ~]$ sudo -i
[root@10 ~]# vi /etc/ssh/sshd_config
複製代碼
3.修改SSH安全認證以下
PasswordAuthentication yes
複製代碼
4.修改完成,退出sshd_config後,更換SSH登錄密碼,我這裏使用的密碼是evan123
[root@10 ~]# passwd
Changing password for user root.
New password:
BAD PASSWORD: The password fails the dictionary check - it is too simplistic/systematic
Retype new password:
passwd: all authentication tokens updated successfully.
複製代碼
5.重啓SSH服務,使配置生效
[root@10 ~]# systemctl restart sshd
複製代碼
6.測試SSH鏈接 查看當前Centos系統ip,經過ip add
命令進行查看
[root@10 /]# ip add
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
link/ether 52:54:00:8a:fe:e6 brd ff:ff:ff:ff:ff:ff
inet 10.0.2.15/24 brd 10.0.2.255 scope global noprefixroute dynamic eth0
valid_lft 74572sec preferred_lft 74572sec
inet6 fe80::5054:ff:fe8a:fee6/64 scope link
valid_lft forever preferred_lft forever
3: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
link/ether 08:00:27:ba:0a:28 brd ff:ff:ff:ff:ff:ff
inet 192.168.100.9/24 brd 192.168.100.255 scope global noprefixroute dynamic eth1
valid_lft 160972sec preferred_lft 160972sec
inet6 fe80::a00:27ff:feba:a28/64 scope link
valid_lft forever preferred_lft forever
複製代碼
能夠看到,當前外網ip是192.168.100.9
退出虛擬機,回到主體機器,測試是否能夠鏈接上虛擬機上的Centos系統
192:~ evan$ ssh root@192.168.100.9
The authenticity of host '192.168.100.9 (192.168.100.9)' can't be established. ECDSA key fingerprint is SHA256:1yutVoFjWAa0o2vCNP+kOxS/rITjxhqTV/48XsTNKGo. Are you sure you want to continue connecting (yes/no)? yes Warning: Permanently added '192.168.100.9' (ECDSA) to the list of known hosts. root@192.168.100.9's password:
Last login: Mon Jan 27 12:19:55 2020 from 127.0.0.1
-bash: warning: setlocale: LC_CTYPE: cannot change locale (UTF-8): No such file or directory
[root@10 ~]#
複製代碼
此時已經成功鏈接上,下一步開始Docker安裝
1.執行如下命令清理以前已安裝的Docker文件,若是以前曾經安裝過
sudo yum remove docker \
docker-client \
docker-client-latest \
docker-common \
docker-latest \
docker-latest-logrotate \
docker-logrotate \
docker-engine
複製代碼
由於這個系統是新安裝,以前沒有Docker相關文件,執行結果以下:
[root@10 /]# sudo yum remove docker \
> docker-client \
> docker-client-latest \
> docker-common \
> docker-latest \
> docker-latest-logrotate \
> docker-logrotate \
> docker-engine
Failed to set locale, defaulting to C
Loaded plugins: fastestmirror
No Match for argument: docker
No Match for argument: docker-client
No Match for argument: docker-client-latest
No Match for argument: docker-common
No Match for argument: docker-latest
No Match for argument: docker-latest-logrotate
No Match for argument: docker-logrotate
No Match for argument: docker-engine
No Packages marked for removal
複製代碼
2.輸入如下命令安裝環境必要依賴
sudo yum install -y yum-utils \
device-mapper-persistent-data \
lvm2
複製代碼
3.經過如下命令配置阿*雲鏡像加速器,不然下載鏡像會比較慢,這裏鏡像加速器作了脫敏處理,你們能夠本身去申請一個
sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": ["https://***.mirror.aliyuncs.com"]
}
EOF
sudo systemctl daemon-reload
sudo systemctl restart docker
複製代碼
怎麼獲取鏡像加速器地址,能夠查看我另外一篇文章 使用Docker安裝Oracle
4.設置Docker倉庫,Docker默認倉庫hub.docker.com
sudo yum-config-manager \
--add-repo \
https://download.docker.com/linux/centos/docker-ce.repo
複製代碼
5.安裝Docker
sudo yum install -y docker-ce docker-ce-cli containerd.io
複製代碼
6.啓動Docker服務
sudo systemctl start docker
複製代碼
7.經過Docker倉庫自帶鏡像,測試Docker是否已經安裝成功
[root@10 /]# sudo docker run hello-world
Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
1b930d010525: Pull complete
Digest: sha256:9572f7cdcee8591948c2963463447a53466950b3fc15a247fcad1917ca215a2f
Status: Downloaded newer image for hello-world:latest
Hello from Docker!
This message shows that your installation appears to be working correctly.
To generate this message, Docker took the following steps:
1. The Docker client contacted the Docker daemon.
2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
(amd64)
3. The Docker daemon created a new container from that image which runs the
executable that produces the output you are currently reading.
4. The Docker daemon streamed that output to the Docker client, which sent it
to your terminal.
To try something more ambitious, you can run an Ubuntu container with:
$ docker run -it ubuntu bash
Share images, automate workflows, and more with a free Docker ID:
https://hub.docker.com/
For more examples and ideas, visit:
https://docs.docker.com/get-started/
複製代碼
Docker會自動下載鏡像,若是在本地查找不到
1.從遠方倉庫拉去Tomcat鏡像,這裏不帶版本號默認拉取最新版本
docker pull tomcat
複製代碼
2.啓動Tomcat容器,指定容器命名爲evan-tomcat,而且配置容器端口9090映射到內置mysql 3306端口
docker run -d --name evan-tomcat -p 9090:8080 tomcat
複製代碼
1.從遠方倉庫拉去Tomcat鏡像,這裏不帶版本號默認拉取最新版本
docker pull mysql
複製代碼
2.啓動MySQL容器,並更名爲evan-mysql,配置容器端口 3301映射到3306端口,並設置密碼爲evan123
docker run -d --name evan-mysql -p 3301:3306 -e MYSQL_ROOT_PASSWORD=evan123 --privileged mysql
複製代碼
1.經過如下Docker指令能夠查看上面咱們安裝和啓動的容器是否正常運行:
[root@10 /]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
358207fa8d8b tomcat "catalina.sh run" 3 minutes ago Up 3 minutes 0.0.0.0:9090->8080/tcp evan-tomcat
b58999f0524f mysql "docker-entrypoint.s…" 5 minutes ago Up 5 minutes 33060/tcp, 0.0.0.0:3301->3306/tcp evan-mysql
[root@10 /]#
複製代碼
2.咱們能夠經過上面的容器ID去進入到容器內部,這裏以Tomcat爲例子:
[root@10 /]# docker exec -it 358207fa8d8b /bin/bash
root@358207fa8d8b:/usr/local/tomcat# ls
BUILDING.txt LICENSE README.md RUNNING.txt conf lib native-jni-lib webapps work
CONTRIBUTING.md NOTICE RELEASE-NOTES bin include logs temp webapps.dist
root@358207fa8d8b:/usr/local/tomcat#
複製代碼
這樣咱們本章全部環境SETUP已經順利完成,後面的章節將會更深刻介紹容器的原理、集羣部署、管理以及結合真實微服務的應用。
1.在Mac中安裝Visualbox時失敗,提示「the installation failed」
緣由是MacOS阻止了VirtualBox安裝kernel extension。在system preferences中選擇security&privacy在general中點擊下方的allow便可解決。
2.vagrant up
命令啓動失敗,提示No Usable default provider could be found for your system
這是因爲Vagrant與Virtualbox版本不一致,Vagrant的版本比Virtualbox的舊,能夠將Virtualbox降級,或者直接使用本文推薦的版本