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降级,或者直接使用本文推荐的版本