实验环境:Windows操作系统,阿里云资源,Docker
实验内容和要求:安装Docker并进行相关实验,熟悉Docker的相关操作。实验包括Docker的安装、镜像和容器的使用、容器的连接、容器间的通信和使用。Docker是一个开源的应用容器引擎,属于Linux容器的一种封装,是目前最流行的Linux容器解决方案。docker可以为任何应用创建一个轻量级、可移植的容器,然后容器可以运行在任何安装有docker的平台上。
实验原理和机制:Docker是一种构建在LXC之上,基于进程容器的轻量级虚拟化解决方案,实现了应用程序级别的资源隔离。通过Docker技术,开发者把应用以及依赖包封装到一个镜像中,可以发布到Linux或Windows机器上。
Docker镜像就像停止运行的容器,镜像由多个层组成,每层叠加之后,从外部看来就如一个独立的对象。镜像内部是一个精简的操作系统(OS),同时还包含应用运行所必须的文件和依赖包。Docker镜像存储在镜像仓库服务(Image Registry)当中。Docker客户端的镜像仓库服务是可配置的,默认使用Docker Hub。镜像仓库服务包含多个镜像仓库(Image Repository)。同样,一个镜像仓库中可以包含多个镜像。
容器是镜像的运行时实例。正如从虚拟机模板上启动VM一样,用户也同样可以从单个镜像上启动一个或多个容器。虚拟机和容器最大的区别是容器更快并且更轻量级——与虚拟机运行在完整的操作系统之上相比,容器会共享其所在主机的操作系统/内核。容器中可以运行一些网络应用,要让外部也可以访问这些应用,可以通过-P或-p参数来指定端口映射。
容器之间可通过IP、Docker DNS Server或joined容器三种方式通信。两个容器要能通信,必须要有属于同一个网络的网卡。满足这个条件后,容器就可以通过IP交互了。具体做法是在容器创建时指定相应的网络,或者将现有容器加入到指定网络。通过IP访问容器虽然满足了通信的需求,但还是不够灵活。因为我们在部署应用之前可能无法确定IP,部署之后再指定要访问的IP会比较麻烦。对于这个问题,可以通过docker自带的 DNS 服务解决。从 Docker 1.10 版本开始,docker daemon实现了一个内嵌的DNS server,使容器可以直接通过“容器名”通信。但使用 docker DNS 有个限制:只能在user-defined网络中使用。也就是说,默认的bridge网络是无法使用DNS的。joined容器可以使两个或多个容器共享一个网络栈,共享网卡和配置信息,joined容器之间可以通过127.0.0.1直接通信。
Nginx是一款轻量级的Web服务器/反向代理服务器及电子邮件(IMAP/POP3)代理服务器,其特点是占有内存少,并发能力强。
实验步骤:
实验准备:远程登录到ECS服务器
安装Docker服务
- 运行以下命令安装Docker的依赖库。这里yum-utils 提供了 yum-config-manager,并且 device mapper存储驱动序需要 device-mapper-persistent-data 和 lvm2。
yum install -y yum-utils device-mapper-persistent-data lvm2 - 运行以下命令添加Docker CE的软件源信息。Docker版本分为 CE(Community Edition: 社区版) 和 EE(Enterprise Edition: 企业版),这里选择Docker CE。
yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo - 运行以下命令安装Docker CE。
yum -y instal ldocker-ce - 运行以下命令查看Docker版本:
docker -v - 运行以下命令启动Docker服务
systemctl start docker - 运行以下命令查看Docker服务状态
servicedocker status
Docker启动成功后显示如下信息:
说明:停止Docker服务使用命令: systemctl stop docker - 运行以下命令测试运行Docker Hello World
docker run hello-world
Docker基本操作
本步骤在Docker容器中通过 Python Flask运行一个WEB应用 - 列出镜像列表
docker images
命令运行结果如下所示:
说明:REPOSITORY表示镜像的仓库源。同一仓库源可以有多个TAG,代表这个仓库源的不同版本。如Ubuntu仓库源里,有15.10、14.04等多个不同的版本,使用 REPOSITORY:TAG 来定义不同的镜像。
2.拉取镜像:把指定镜像拉取到本地
docker pull training/webapp
命令运行结果如下所示:
说明:拉取镜像需要较长时间,当拉取镜像失败时,建议配置DockerHub镜像加速器。具体方法是增加一个文件/etc/docker/daemon.json,并添加上registry-mirrors键值,步骤如下:
vi /etc/docker/daemon.json
在文件中添加以下内容
“registry-mirrors”: [“https://registry.docker-cn.com”]
完成后点击“ECS”键,然后输入:wq保存退出文档。再重新执行拉取镜像命令。
3.运行容器
docker run -d -P training/webapp python app.py
命令运行结果如下所示:
4.查看正在运行的容器
docker ps
命令运行结果如下所示(可以看到Docker 开放了 5000 端口(默认 Python Flask 端口)映射到主机端口49153上)
5.使用ECS实例IP和端口号,通过浏览器访问WEB应用。
在浏览器地址栏输入http://ECS 实例公网地址:端口号并按回车键,本示例运行结果如下:
6.查看 WEB 应用程序日志,命令格式:docker logs 容器ID或者名字
docker logs -f 88bd74928ed7
本示例运行结果:
7.停止 WEB 应用容器,命令格式: docker stop容器ID或者名字
docker stop
8.移除WEB应用容器,命令格式: docker rm容器ID或者名字
docker rm aacead966f37
注意:删除容器时,容器必须是停止状态,否则会报错误。
通过DNS server进行通信
通过docker daemon内嵌的DNS server使容器可以直接通过“容器名”通信。如果在容器启动时没有指定 --dns 和 --dns-search,Docker 会默认用宿主主机上的 /etc/resolv.conf 来配置容器的 DNS。
- 创建bridge网络my_net1,指定–subnet和–gateway参数
docker network create --driver bridge --subnet 172.22.16.0/24 --gateway 172.22.16.1 my_net1
2.查看网络配置:
docker network inspect my_net1
3.基于busybox镜像运行容器bbox1,并连接到新建的桥接网络my_net1网络。busybox是一个软件工具箱,集成了linux中几百个常用的linux命令以及工具。
docker run -i -t -d --network=my_net1 --name=bbox1 busybox - 基于busybox镜像运行容器bbox2,并加入到 my_net1 网络
docker run -it --network=my_net1 --name=bbox2 busybox
5.在bbox2容器用ping命令测试连接到bbox1。
ping -c 3 bbox1
运行结果如下:
6.用命令exit退出bbox2
通过joined 容器通信
joined 容器可以使两个或多个容器共享一个网络栈,共享网卡和配置信息,joined容器之间可以通过 127.0.0.1直接通信。
- 创建一个 httpd 容器,名字为 web1 :docker run -d -it --name=web1 httpd
- 创建一个busybox 容器并通过–network=container:web1指定joined 容器为web1。
docker run -it --network=container:web1 busybox - 在busybox容器中用 ip a命令查看网络配置信息,然后用命令exit退出。
- 进入web1容器:
docker exec -it web1 /bin/bash - 查看web1的网络配置信息
注意:如果在web1容器中找不到ip命令,则进行资源更新和升级。执行以下升级操作:
apt-get update
apt-get upgrade
apt-get install iproute2 iproute2-doc
ip a(可以看到:这里web1容器 和busybox容器的网卡 mac 地址、IP 完全一样,它们共享了相同的网络栈)
6.用命令exit退出web1容器。
7.列出容器列表,查看busybox容器的名字。
本示例busybox容器的名字是brave_lehmann
- 启动并进入busybox容器
docker start hardcore_nobe1
docker attach hardcore_nobe1
9.在busybox 容器中直接用 127.0.0.1 访问 web1 的 http 服务,并用命令exit退出busybox容器。
wget 127.0.0.1
运行结果如下:
实验总结:
报错:
使用cmd 登陆发现服务器拒绝登陆,重新开始实验
两个容器无法通过“容器名”通信时的解决方案
1.要先启动docker。
2.新建daemon.json配置文件,设置镜像源加速地址。
3.修改daemon.json文件,配置全部容器的DNS,重启docker使之生效
4.进行资源更新和升级。(apt-get update/apt-get upgrade)
心得体会:使用Docker可以通过定制应用镜像来实现持续集成、持续交付、部署。开发人员可以通过DockerFile来进行镜像构建,并结合 持续集成系统进行集成测试,而运维人员则可以直接在生产环境中快速部署该镜像,甚至结合持续部署系统进行自动部署。而使用DockerFile使镜像构建透明化,不仅仅开发团队可以理解应用运行环境,也方便运维团队理解应用运行所需条件,帮助更好的生产环境中部署该镜像。Docker使应用的分层存储以及镜像的技术,使得应用重复部分的复用更为容易,也使得应用的维护更新更加简单,基于基础镜像进一步扩展镜像也变的非常简单。此外,Docker团队同各个开源项目团队一起维护了一大批高质量的官方镜像,既可以直接在生产环境使用,又可以作为基础进一步定制,大大的降低了应用服务的镜像制作成本。