Docker 可谓是开启了容器化技术的新时代,现在无论大中小公司基本上都对容器化技术有不同程度的尝试,或是已经进行了大量容器化的改造。伴随着 Kubernetes 和 Cloud Native 等技术和理念的普及,也大大增加了业务容器化需求。

而这一切的推进,不可避免的技术之一便是构建容器镜像。

在本场 Chat 中,会讲到如下内容:

  • 深入内部从根本上解释 Docker 镜像是什么
  • Docker 镜像常规管理操作
  • 了解 Docker 的网络模型
  • 如何构建 Docker 镜像
  • 逐步分解构建 Docker 镜像的最佳实践
  • 了解 Docker 在实际项目中应用

适合人群: 对Docker的初学者以及任何有兴趣的开发人员

教程目标

Docker 已经上市很多年,不是什么新鲜事物了,很多企业或者开发同学以前也不多不少有所接触,但是有实操经验的人不多,本系列教程主要偏重实战,尽量讲干货,会根据本人理解去做阐述,具体官方概念可以查阅官方教程,本章目标如下:

  • 了解什么是 Docker
  • 了解 Docker 解决了什么
  • 了解什么是镜像和容器
  • 了解容器与虚拟机的区别
  • 了解 Vagrant 与 Docker 的区别
  • 了解 Docker 引擎和架构
  • 了解 Docker 的镜像分层
  • 了解 VirturalBox 和 Docker 如何搭配使用
  • 了解主体机器如何与客体机器上的容器进行通信
  • 了解 Vagrant、VirtualBox、Docker 搭建与基本操作

预备工作

因为我是 Mac 用户,所以这里 VirturalBox 和 vagrant 使用的是 Mac 版本,大家到官网各自下载对应的系统版本即可,强烈建议使用迅雷下载!

  • VirtualBox-6.0.14-133895-OSX.dmg
  • Vagrant2.2.6x86_64.dmg
  • Centos7 镜像

Vagrant 下载VirtualBox 下载

容器与虚拟化技术

什么是 Docker**

简单来说 Docker 是一款可以将应用程序与基础设施分离、代码及其所有依赖项打包,使应用程序能够从一个计算环境快速可靠地运行到另一个计算环境,达到快速交付、测试、部署的容器化技术。

使用 Linux 容器部署应用程序称为容器化。

为什么要用 Docker

我们可以反过来思考,不用 Docker 这些容器化技术会怎么样,会遇到什么问题和瓶颈。

事例

想要发布一个应用到测试、生产环境使用,都会经历以下流程:

物理机时代

每个团队会需要申请一台物理机作为测试开发环境,进行一系列的环境搭建通过上图可以看出直接使用物理机会存在一些问题

  • 成本高 - 需要购买一台实体机器,没办法共享
  • 部署慢 - 发布一个应用需要走漫长的流程
  • 资源浪费 - 平时应用实际用不到那么多物理资源,除了搞活动时期,大部分时候处于闲置状态,还有一部分资源被操作系统运行程序占用
  • 硬件限制 - 不同硬件厂商有兼容问题
  • 不利于迁移扩展 - 如果想迁移到其他服务器上,需要重头打包配置应用依赖

虚拟化时代

在虚拟化技术出现之后,每个团队只需要申请一台虚拟机,多台虚拟机可以共享同一台物理机,大大降低了成本,一定程度上提升了资源利用率,当公司搞活动时系统需要扩展,只需要通过虚拟机镜像创建多个虚拟机即可,提升了系统扩展性和可用性Hypervisor,又称虚拟机监视器(英语:virtual machine monitor,缩写为 VMM),是用来建立与执行虚拟机器的软件、固件或硬件。被 Hypervisor 用来执行一个或多个虚拟机器的电脑称为主体机器(host machine),这些虚拟机器则称为客体机器(guest machine)。hypervisor 提供虚拟的作业平台来执行客体操作系统(guest operating systems),负责管理其他客体操作系统的执行阶段;这些客体操作系统,共同分享虚拟化后的硬件资源。(引用自百度百科)

从上图不难发现,主机机器会为每个客体机器(虚拟机)提前分配好资源,与物理机时代一样,实际上应用本身可能并不需要那么多物理资源,有一部分资源被操作系统所占用,大部分时候处于闲置状态,仍然存在一些问题如下:

  • 资源利用率低 - 操作系统占用了一部分资源
  • 移植性差 - 虚拟机上的应用对操作系统有较大依赖
  • 启动速度慢 - 每次运行一个虚拟机上的应用都需要先启动系统
  • 部署麻烦 - 如果从开发环境切换到测试和生产环境,仍然需要重新搭建应用相关依赖

容器化时代

Docker 容器类似沙箱,每个容器之间相互独立、资源隔离、互不干扰,Docker 容器化技术出现后,基本解决了上面提到的问题,Docker 有以下优势:

  • 启动速度更快: 秒级启动。
  • 快速的部署和交付: 开发者可以使用一个标准的镜像来构建一套开发容器,开发完成之后, 运维人员可以直接使用这个容器来部署代码。
  • 更高效的虚拟化: 它是内核级的虚拟化,因此可以实现更高的性能和效率。
  • 高效的迁移: Docker 可以运行在不同的平台,用户可以轻松的将一个应用从一个平台迁移到另一个平台。
  • 节省开支: Docker 容器除了运行其中应用外,基本不消耗额外的系统资源,一台设备可以运行上千个容器。
  • 资源隔离:可以对 Docker 进行资源限制,每个容器可以享用自己的物理资源,互不干扰

从上图可以看到,我把物理资源变成可选了,这是因为默认的情况下,docker 没有对容器进行硬件资源的限制,当一台主机上运行几百个容器,这些容器虽然互相隔离,但是底层却使用着相同的 CPU、内存和磁盘资源。如果不对容器使用的资源进行限制,那么容器之间会互相影响,小的来说会导致容器资源使用不公平;大的来说,可能会导致主机和集群资源耗尽,服务完全不可用。

Docker 提供资源隔离机制,利用 Linux 内核的 namespace 机制来做容器之间的隔离,通过内核的 cgroups 机制来做容器的资源限制(CPU、Memory、Disk 等)。

但是直接在主体机器安装 Docker,也会导致 Docker 容器直接依赖主体机器操作系统,没办法实现多租户隔离,后面章节会提到对应解决方案。

什么是容器镜像和容器

镜像是一个可执行包,包含运行应用程序所需的所有内容——代码、运行时、库、环境变量和配置文件。容器是通过运行镜像启动容器,是镜像的运行时实例。镜像实际上就是一个容器的模板,通过这个模板可以创建很多相同的容器。

通过 Java 去类比理解 Docker 的一些概念:

  • Class 文件 - 相当于 Docker 镜像,定义了类的一些所需要的信息
  • 对象 - 相当于容器,通过 Class 文件创建出来的实例
  • JVM - 相当于 Docker 引擎,可以让 Docker 容器屏蔽底层复杂逻辑,实现跨平台操作

容器与虚拟机的区别

容器在 Linux 上本地运行,并与其他容器共享主机的内核。它运行一个独立的进程,不占用比其他任何可执行程序更多的内存,使其轻量级。

虚拟机(VM) 运行一个成熟的“游客”操作系统,通过虚拟机监控程序对主机资源进行虚拟访问。通常,vm 提供的资源比大多数应用程序所需的要多。

总的来说,容器不需要依赖操作系统,减少了很多系统资源开销,使得容器可以更关注应用的需求,而虚拟机可以为每个应用灵活提供不同的操作系统,避免了 docker 容器直接依赖主体机器操作系统,两者结合使用,可以让整个系统架构更加灵活,扩展性更强。

Vagrant 与 Docker 的区别

其实两款产品没有什么可比性,因为使用场景不同,这里列出来主要是避免一些童鞋误解。Vagrant 是一款管理虚拟机的工具,简化了虚拟机的搭建和管理工作,不需要再像以前一样,需要人工一个个去创建、启动、停止虚拟机,可以通过 vagrant 脚本同一时间轻松搭建和管理多个虚拟机节点。

docker 是一款用于快速交付、测试、部署的工具,简化了应用环境的搭建和管理工作。两者适用范围不同。一个容器就是一个包含了应用执行所依赖的数据(包括 lib,配置文件等等),Docker 可以通过同一个镜像文件快速在不同的环境(开发、测试、生产)搭建多个相同的容器。

Vagrant 是用于管理虚拟机,Docker 用于管理应用环境。

Docker 引擎和架构

Docker 引擎是一个客户端-服务器应用程序,主要组件如下:

  • 服务器是一种长时间运行的程序,称为守护进程(dockerd)命令)。
  • 一个 REST API,它指定了程序可以用来与守护进程对话的接口指导它做什么。
  • 命令行接口(CLI)客户端(docker 命令)。

平时我们使用的 docker 指令都是通过 docker 客户端去与 docker 服务端进行通讯

Docker 架构体系

Docker 使用客户机-服务器架构。

Docker 客户机与 Docker 守护进程进行对话,后者负责构建、运行和分发 Docker 容器。

Docker 客户机和守护进程可以在同一系统上运行,也可以将 Docker 客户机连接到远程 Docker 守护进程。Docker 客户机和守护进程通过 UNIX 套接字或网络接口使用 REST API 进行通信。

Docker 的镜像分层

Docker 镜像是由一系列层构成的。每一层代表镜像 Dockerfile 中的一条指令。除了最后一层之外,每一层都是只读的。Docker 镜像分层最大的好处是共享资源,其他相同环境的软件镜像都共同去享用同一个环境镜像,而不需要每个软件镜像要去创建一个底层环境。上图以 Tomcat 镜像为例子,对于用户而言,用户面向的是一个叠加后的文件系统,我们对 Tomcat 容器做任何操作都会记录在容器层,底层镜像文件不会受影响。Docker 容器底层共享主机内核,只保留少量运行 Image 必须的组件,在容器启动时不需要启动内核空间,所以启动时比虚机较快,开销少,易迁移。

VirturalBox 和 Docker 如何搭配使用

上面章节也提到过,如果我们把 Docker 直接安装在主体机器,会导致 Docker 直接依赖了我们主体机器的操作系统,如果不同的团队共用一台物理机时,没办法做到每个团队或每个环境都独享自己的操作系统和相应的权限。目前一般的部署模式有以下几种:

  • 物理机+Docker 模式 - 适合高 I/O 要求的业务,如一些数据库服务、文件服务、缓存服务等
  • 虚拟机 - 虚拟机的多租户的强隔离特性,保证租户在拥有虚机 root 权限的同时,其他租户和主机的安全
  • 物理机+虚拟机+Docker 混合模式 - 集合上面的优点,既可以提供安全隔离,也能实现灵活扩展和高可用

从上图可以看出,本教程采用的是混合模式,Docker 容器可以在虚拟机内部运行,虚拟机并为它们提供经过验证的隔离,安全属性,移动性,动态虚拟网络等,可实现安全隔离和资源的高利用率。基本应该遵循:不同租户的业务运行采用虚拟机隔离,相似类型的业务部署在同一组容器上的思路。

当虚拟机太多的时候,我们也没办法手动一个个去管理,因此这里用到 Vagrant 工具去管理虚拟机。

主体机器如何与客体机器上的容器进行通信

从上图可以看到,当我们使用 Docker+虚拟机的混合模式时,实际上整体结构可以分为三大部分:主体机器、客体机器和容器。主体机器不能直接访问客体机器上的容器的 IP 地址访问容器,因为不再同一个网段,而要通过客体主机和对应的映射端口访问客体机器的容器。

以 Tomcat 容器作为一个例子,这里虚拟机网络模式默认是bridge方式,在实战部分也有详细步骤,应用部署图如下:我在客体机器 Centos 上启动一个 Tomcat 容器,容器端口为 8080,映射端口为 9090

docker run -d --name evan-tomcat -p 9090:8080 tomcat

通过命令查看得到,主体机器、客体机器、Tomcat 容器 IP 地址(跟图片一致)如下:

  • 主体机器 - 我机器自带的 MacOS,IP 地址为 192.168.100.4
  • 客体机器 - 虚拟机上的 Centos 系统,IP 地址为 192.168.100.9
  • 容器 - Tomcat 容器(linux 内核),IP 地址为172.17.0.3

尝试主体机器(MacOS)访问客体机器(Centos)

192:~ evan$ ping 192.168.100.9PING 192.168.100.9 (192.168.100.9): 56 data bytes64 bytes from 192.168.100.9: icmp_seq=0 ttl=64 time=0.481 ms64 bytes from 192.168.100.9: icmp_seq=1 ttl=64 time=0.477 ms64 bytes from 192.168.100.9: icmp_seq=2 ttl=64 time=0.447 ms64 bytes from 192.168.100.9: icmp_seq=3 ttl=64 time=0.339 ms64 bytes from 192.168.100.9: icmp_seq=4 ttl=64 time=0.400 ms64 bytes from 192.168.100.9: icmp_seq=5 ttl=64 time=0.324 ms

可以看到,主体机器是可以直接与客体机器进行通信,因为在同一个网段

尝试客体机器(Centos)访问 Tomcat 容器

[root@10 /]# ping 172.17.0.3PING 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 ms64 bytes from 172.17.0.3: icmp_seq=2 ttl=64 time=0.043 ms64 bytes from 172.17.0.3: icmp_seq=3 ttl=64 time=0.047 ms64 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+端口方式访问容器,因此主体机器访问的并不是容器真实的端口,而是虚拟机上端口的映射。

环境搭建与实战

使用 Vagrant 管理虚拟机创建 Centos7

1.创建一个 centos7 文件夹

mkdir centos7

2.在当前文件夹初始化 Vagrantfile

vagrant init centos7

输出结果如下:

192:centos7 evan$ vagrant init centos7A `Vagrantfile` has been placed in this directory. You are nowready to `vagrant up` your first virtual environment! Please readthe 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  # SHELLend

4.下载 centos7 镜像文件百度网盘下载官网下载

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 listcentos7 (virtualbox, 0)

可以看到,已经成功添加 centos7

8.根据 Vagrantfile 文件启动创建虚拟机,去到刚才初始化 Vagrantfile 的文件夹,执行vagrant up创建虚拟机,vagrant 会自动根据我们在 Vagrant 配置好的参数来创建虚拟机,注意我们上面添加的虚拟机名字centos7要与配置文件中的config.vm.box = "centos7"一致。(执行过程中,Virtualbox 应用不需要打开)

192:centos7 evan$ vagrant upBringing 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) p2p04) awdl05) llw06) en7: USB 10/100/1000 LAN7) en1: Thunderbolt 18) en2: Thunderbolt 29) en3: Thunderbolt 310) en4: Thunderbolt 411) 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

安装 Docker 之前,需要进入刚才安装好的 Centos7 操作系统,因此需要先设置下 SSH 配置,这里使用的是账号密码登陆

通过 SSH 客户端访问 Centos

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 ~]# passwdChanging password for user root.New password: BAD PASSWORD: The password fails the dictionary check - it is too simplistic/systematicRetype new password: passwd: all authentication tokens updated successfully.

5.重启 SSH 服务,使配置生效

[root@10 ~]# systemctl restart sshd

6.测试 SSH 连接查看当前 Centos 系统 ip,通过ip add命令进行查看

[root@10 /]# ip add1: 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 forever2: 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 forever3: 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.9The 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)? yesWarning: 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 安装

在 Centos 上安装 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-engineFailed to set locale, defaulting to CLoaded plugins: fastestmirrorNo Match for argument: dockerNo Match for argument: docker-clientNo Match for argument: docker-client-latestNo Match for argument: docker-commonNo Match for argument: docker-latestNo Match for argument: docker-latest-logrotateNo Match for argument: docker-logrotateNo Match for argument: docker-engineNo Packages marked for removal

2.输入以下命令安装环境必要依赖

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

3.通过以下命令配置阿里云镜像加速器,否则下载镜像会比较慢,这里镜像加速器做了脱敏处理,大家可以自己去申请一个

sudo mkdir -p /etc/dockersudo tee /etc/docker/daemon.json <<-'EOF'{  "registry-mirrors": ["https://***.mirror.aliyuncs.com"]}EOFsudo systemctl daemon-reloadsudo 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-worldUnable to find image 'hello-world:latest' locallylatest: Pulling from library/hello-world1b930d010525: Pull complete Digest: sha256:9572f7cdcee8591948c2963463447a53466950b3fc15a247fcad1917ca215a2fStatus: Downloaded newer image for hello-world:latestHello 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 bashShare 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 会自动下载镜像,如果在本地查找不到

通过 Docker 安装 Tomcat

1.从远方仓库拉去 Tomcat 镜像,这里不带版本号默认拉取最新版本

docker pull tomcat

2.启动 Tomcat 容器,指定容器命名为 evan-tomcat,并且配置容器端口 9090 映射到内置 mysql 3306 端口

docker run -d --name evan-tomcat -p 9090:8080 tomcat
通过 Docker 安装 Mysql

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 psCONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                               NAMES358207fa8d8b        tomcat              "catalina.sh run"        3 minutes ago       Up 3 minutes        0.0.0.0:9090->8080/tcp              evan-tomcatb58999f0524f        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/bashroot@358207fa8d8b:/usr/local/tomcat# lsBUILDING.txt     LICENSE  README.md  RUNNING.txt  conf     lib   native-jni-lib  webapps       workCONTRIBUTING.md  NOTICE   RELEASE-NOTES  bin          include  logs  temp        webapps.distroot@358207fa8d8b:/usr/local/tomcat# 

这样我们本章所有环境 SETUP 已经顺利完成,后面的章节将会更深入介绍容器的原理、集群部署、管理以及结合真实微服务的应用。

Q&A

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

附录

Vagrant 常用命令

  • vagrant up启动虚拟机
  • vagrant ssh
    进入虚拟机
  • )vagrant status查看 centos7 的状态
  • vagrant halt停止/关闭 centos7
  • vagrant destroy删除 centos7
  • vagrant status查看当前 vagrant 创建的虚拟机
  • Vagrantfile 中也可以写脚本命令,使得 centos7 更加丰富但是要注意,修改了 Vagrantfile,要想使正常运行的 centos7 生效,必须使用 vagrant reload

Docker 常用命令

  • docker pull
    拉取镜像到本地
  • docker run
    根据某个镜像创建容器
  • -d 让容器在后台运行,其实就是一个进程
  • --name 给容器指定一个名字
  • -p 将容器的端口映射到宿主机的端口
  • docker exec -it
    进入到某个容器中并交互式运行

阅读全文: http://gitbook.cn/gitchat/activity/5e5b80804627e8105f208e3d

您还可以下载 CSDN 旗下精品原创内容社区 GitChat App , GitChat 专享技术内容哦。

Docker深入浅出系列相关推荐

  1. Docker深入浅出系列 | 容器初体验

    Docker深入浅出系列 | 容器初体验 教程目标 Docker已经上市很多年,不是什么新鲜事物了,很多企业或者开发同学以前也不多不少有所接触,但是有实操经验的人不多,本系列教程主要偏重实战,尽量讲干 ...

  2. Docker深入浅出系列 | 5分钟搭建镜像仓库

    Docker已经上市很多年,不是什么新鲜事物了,很多企业或者开发同学以前也不多不少有所接触,但是有实操经验的人不多,本系列教程主要偏重实战,尽量讲干货,会根据本人理解去做阐述,具体官方概念可以查阅官方 ...

  3. docker 保存 环境持久化_Docker深入浅出系列 | 容器数据持久化

    Docker深入浅出系列 | 容器数据持久化 Docker已经上市很多年,不是什么新鲜事物了,很多企业或者开发同学以前也不多不少有所接触,但是有实操经验的人不多,本系列教程主要偏重实战,尽量讲干货,会 ...

  4. Docker入门系列之二:使用dockerfile制作包含指定web应用的镜像

    2019独角兽企业重金招聘Python工程师标准>>> 在前一篇文章:Docker入门系列之一:在一个Docker容器里运行指定的web应用 里, 我们已经成功地将我们在本地开发的一 ...

  5. Docker入门系列之三:如何将dockerfile制作好的镜像发布到Docker hub上

    这个系列的前两篇文章,我们已经把我们的应用成功地在Docker里通过nginx运行了起来,并且用dockerfile里制作好了一个镜像. Docker入门系列之一:在一个Docker容器里运行指定的w ...

  6. Docker入门系列(一):目标和安排

    Docker入门系列(一) 这个系列的教程来源于docker的官方文档,此文档的目的在于一步一步学习docker的使用方法. 这一系列的教程有如下几篇文档: docker安装启动 构建第一个docke ...

  7. 【SpringBoot深入浅出系列】SpringBoot之实现支付宝扫码支付(沙箱环境编码实现)

    目录 一.准备工作 1.应用 APPID 2.商户私钥,即应用私钥 3.支付宝公钥 4.签名方式 5.字符编码格式 6.支付宝网关 二.沙箱环境编码实现 1.项目说明 2.创建 Spring Init ...

  8. 深入浅出系列1:词向量

    深入浅出系列1:词向量 0.文章结构 词向量简介 one-hot编码 统计语言模型 分布式表征和SVD分解 神经网络语言模型 word2vec fastText(新增文章补充,敬请期待) GloVe( ...

  9. Docker学习系列从零开始之汇总【汇总】

    以下是整个docker学习系列的地址,希望可以给到大家一定的帮助: 1.Docker学习系列从零开始之centos6.5底下安装docker[一] 2.Docker学习系列从零开始之制作docker原 ...

  10. css深入浅出系列之:绝对定位 position:absolute

    css深入浅出系列只是自己在学习css的时候的一些个人见解,有错误的地方,欢迎在评论中指正噢~ 今天主要在以下几个方面来展开: 1.什么是绝对定位 2.如何确定绝对定位元素的定位点 3.absolut ...

最新文章

  1. 机器学习算法基础——数据特征预处理
  2. 函数计算是如何工作的?
  3. 规模估算失准 软件开发成空中楼阁
  4. html 给 ol添加abc,英语abc怎么写
  5. 聚类算法学习指南(二)
  6. 使用 Intellij Idea 打包 java 工程为可执行 jar 包
  7. python字符串大全_Python 字符串操作方法大全
  8. 运行java黑窗口是什么意思_黑窗口运行java文件步骤
  9. net 将WebService生成dll文件
  10. Oracle 10G R2 让表常驻内存
  11. Android手势监听类GestureDetector的使用
  12. mysql 类似 oracle connect by_mysql实现层级查询,相似oracle里的connect by prior
  13. H5游戏《守塔兵团》你必须要知道的4件事
  14. 07-android-基站定位
  15. 2019 杭电多校第6场 HDU - 6638 Snowy Smile 线段树 最大子段和
  16. 1和4互素吗_互素是什么意思判别方法,1和2互素,互素
  17. 金种子前三季净利亏损1.44亿 营收不及成本增速致毛利率下滑
  18. (转)周鸿祎产品秘笈:小版本成就大产品
  19. Win7键盘组合快捷键大全
  20. PSP 自制程序 小记

热门文章

  1. Spec文件中判断是升级or卸载
  2. Unity3D——打飞碟游戏(2)
  3. 零基础学UI设计难吗?
  4. 【调色台】达芬奇调色台系列
  5. 半小时一篇文过完C语言基础知识点
  6. ubuntu 16.04+Titan Xp + Cuda 9.0 + Cudnn 7.0 + Caffe
  7. 用java实现首字母大写_java实现每个单词首字母大写
  8. 【路径规划】基于改进差分实现三维多无人机协同航迹规划matlab源码
  9. mac视频太大怎么压缩 苹果电脑怎么压缩视频大小的软件
  10. IBM建立大中华区云计算中心供验证测试