docker是什么以及它的优势是什么?
快速获取开箱即用的程序
docker使得所有传输文件如同日常QQ传输文件一样,执行一个docker命令就能让发送方把鲸鱼派过来将程序派送到超级码头上而接受方则可以让鲸鱼从超级码头运输过来从而获取程序。
管理方便
在docker容器中,只需一条命令就可以对docker进行修改,而存储在服务器上时需要我们到文件位置进行修改。
书同文
诸多程序命令各不相同,例如tomcat的启动命令./startup.sh
,nginx
的启动命令./nginx
,而docker则这些启动命令封装起来,只需要记住docker的命令就可以对其进行操作
隔离
docker
使用一种叫做LXC
的轻量级容器化虚拟技术,通过cgroup
和namespace
等限制,隔离进程组所使用的物理资源,比如CPU,内存等等资源。而且相对于虚拟机而言,该技术创建一个隔离的空间更快。
为什么要使用docker
环境一致性
docker能保证运行环境一致性,不会出现开发/测试/生产由于环境配置不一致导致的各种问题,docker将配置打包放在鲸鱼上,当需要使用时,由鲸鱼给我们送到别的环境上使用,一次配置多次使用。
限定进程使用内存的大小
过去我们常遇到某个程序死循环打爆内存导致其他程序一起挂了,当我们有了docker后,它会再其使用超过最大使用内存时被docker杀掉。
部署简单方便
例如某购物平台在双十一这个节点时,需要搭建更加庞大的集群时,过去可能每台服务器都需要部署各种各样的服务并且还可能起不来,那么手工一台台配置,耗时耗力,而docker基于镜像只需要一两条命令就可以完成服务的部署
docker的三叉戟:镜像、容器、仓库
镜像
镜像的英文名叫image
,即我们打包好的应用程序。
从本质上来说镜像就是一系列文件,可以包括我们应用程序的文件,也可以包括我们应用的运行环境的文件。
这里需要提到联合文件系统,一种分层的文件系统,它可以使不同层级的文件在某个统一的层级上看到。
比例文件夹folder1
下有文件file1
、file2
,文件夹folder2
下有文件file3
。通过联合文件系统我们就可以使得在最上层的文件夹folder3
看到这两个文件夹的文件。
通过这种方式可以实现文件的分层,folder1
可以把它看作第一层,folder2
可以把它看作第二层,每一层有每一层自己的文件,docker就是利用了这种分层的概念实现了镜像存储,将操作系统引导、基础镜像、用户所需的各种程序进行分层,docker镜像系统的每一层都是只读的,然后把每层加载完成后这些文件会被看成是同一个目录,这样的一个文件系统我们称之为镜像。
容器
镜像和容器的关系,就像类
和实例
一样,镜像是静态的定义,而容器则是镜像运行时的实体。每个容器运行时,其实是在镜像上面再创建一个当前容器的存储层(容器层),容器的实质是进程,我们通过镜像创建的进程称之为程序。
上面说的镜像使用的是分层存储,容器也是如此。大家可以把容器想象成一台虚拟机,只不过与虚拟机不同的是,容器中的文件系统是分层的,只有最上层可以写,其它层都是只读的。这使我们需要修改镜像文件时,它会把所需要的文件拷到最顶层,而读文件则是自顶向下。由于容器的最上一层是可以修改的,镜像是不能修改的,这样就能保证镜像可以生成多个容器独立运行。
容器与镜像的区别在于最顶层的可写层的不同,在容器中添加或者修改数据的所有读写操作都会存储在此可写层(容器层)中,当容器被删除后,该可写层也会被删除,而基础镜像则保持不变。如果要数据不丢失,应该使用数据卷(Volume
)或者绑定宿主机目录,这些位置的读写会跳过。
仓库
我们需要的镜像通过docker仓库进行传输,docker自己提供了hub.docker.com
,但是非常慢,可以使用国内网易蜂窝提供的https://c.163yun.com/hub#/m/home/,或者阿里云https://dev.aliyun.com/search.html
docker安装
笔者这边使用的是CentOS
系统,Docker要求CentOS
系统内核版本要高于3.10,所以在安装前要确认下你当前的内核版本
Docker的自动化安装
Docker官方和国内daocloud都提供了一键安装的脚本,使得Docker的安装更加便捷。
官方的一键安装方式:
curl -fsSL https://get.docker.com | bash -s docker --mirror Aliyun
国内 daocloud
一键安装命令:
curl -sSL https://get.daocloud.io/docker | sh
手动安装
1、输入以下命令可以查看内核版本
uname -r
2、安装前确保移除干净旧依赖(卸载旧版本的Docker)
yum remove docker \
docker-client \
docker-client-latest \
docker-common \
docker-latest \
docker-latest-logrotate \
docker-logrotate \
docker-selinux \
docker-engine-selinux \
docker-engine \
docker-ce
3、安装依赖设置yum仓库。新主机上首次安装Docker Engine-Community之前,需要设置Docker仓库。此后可从仓库安装和更新Docker。
yum install -y yum-utils \
device-mapper-persistent-data \
lvm2
3.1、设置仓库,使用官方源地址设置命令如下:
yum-config-manager \
--add-repo \
https://download.docker.com/linux/centos/docker-ce.repo
不过官方的源地址比较慢,可以将上述地址更换为国内地址:
- 清华大学源:https://mirrors.tuna.tsinghua.edu.cn/docker-ce/linux/centos/docker-ce.repo
或者编辑/etc/docker/daemon.conf
(若不存在则新建)
vim /etc/docker/daemon.conf
加入以下内容:
{
"registry-mirrors":["https://6kx4zyno.mirror.aliyuncs.com","http://hub-mirror.c.163.com","https://registry.docker-cn.com"]
}
4、docker安装
yum install docker-ce docker-ce-cli containerd.io
docker-ce
为社区免费版本。安装完成之后的默认是未启动的,需要进行启动操作。
如果不需要docker-ce-cli
或containerd.io
可直接执行如下命令:
yum install -y docker-ce
5、启动并加入开机启动
# 启动命令
systemctl start docker
# 开机启动命令
systemctl enable docker
6、验证是否安装成功
# 查看docker版本
docker version
# 拉取镜像
sudo docker pull hello-world
# 执行hello-world
sudo docker run hello-world
执行成功后,控制台如显示以下内容,则说明Docker安装成功:
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常用命令
安装完成Docker之后,这里汇总列一下常见的Docker操作命令:
- 搜索仓库镜像:
docker search
镜像名 - 拉取镜像:
docker pull
镜像名 - 查看正在运行的容器:
docker ps
- 查看所有容器:
docker ps -a
- 删除容器:
docker rm container_id
- 查看镜像:
docker images
- 删除镜像:
docker rmi image_id
- 启动(停止的)容器:
docker start
容器ID - 停止容器:
docker stop
容器ID - 重启容器:
docker restart
容器ID - 启动(新)容器:
docker run -it ubuntu /bin/bash
- 查看docker性能:
docker stats
- 查看日志:
docker logs
容器ID - 进入容器:
docker attach 容器ID
或docker exec -it 容器ID /bin/bash
,推荐使用后者。 - 服务自启动开启:
docker update --restart=always [容器ID前3位]
- 服务自启动关闭:
docker update --restart=no [容器ID前3位]
实战部署Nginx
首先我们打开网易蜂巢镜像中心https://c.163yun.com/hub#/m/home/,搜索nginx
镜像
点击进去复制下载地址
回到服务器输入docker pull
并黏贴刚刚复制的地址
docker pull hub.c.163.com/library/nginx:latest
完成后可以通过docker images
查看是否有nginx镜像,下图可以看到笔者已经成功安装好nginx镜像了
然后我们将nginx启动起来,下面是使用前台方式启动,这种方法不推荐使用,这边只展示。
docker run hub.c.163.com/library/nginx
后台启动方式
docker run -d hub.c.163.com/library/nginx
通过下面命令查看运行的容器
docker ps
可以看到笔者的nginx已经启动成功了
我们可以通过浏览器访问nginx进而验证docker
部署nginx
成功了
容器内部实操
查看nginx
进程id号(CONTAINER ID)
docker ps |grep nginx
运行命令docker exec -it CONTAINER ID bash
,命令如下:
docker exec -it fa9213c8a454 bash
- -i保证我们的输入有效,即使在没有detach的情况下也能运行.
- -t表示将分配给我们一个伪终端.我们将在伪终端输入我们的内容.
输入命令后,我们就像进入一个新的操作系统一样
我们可以使用ps -ef
命令确认nginx
是否在这个容器中运行,但是要确保有ps
命令,如果没有可以通过下面两条命令安装下。
apt-get update
apt-get install procps
安装完成后,我们再次键入ps -ef
既可以看到nginx是否在运行了
输入exit
即可退出返回原来系统
docker网络
网络介绍
我们都知道docker
的隔离性,网络也是个隔离性的一部分,Linux使用了命名空间来进行资源的隔离,比如pid
namespace
就是用来隔离进程的,mount namespace
是用来隔离文件系统的,network namespace
是用来隔离网络的。每一个network namespace
都提供了一个独立的网络环境,包括网卡路由iptable
规则等等,都是与其它的network namespace
隔离的。
- docker容器在默认情况下,一般会分配一个独立的
network namespace
,也就是网络类型中的Bridge模式。
因为Bridge
模式使用的是独立的network namespace
,那么就需要一种技术让服务器和docker容器的端口构建映射关系,以确保外部用户可以通过端口访问到docker
容器。 - 还有一种类型是
Host
模式,如果在启动容器的时候指定使用Host
模式,那么这个容器将不会获得一个独立的network namespace
,而是和主机共同使用一个,这个时候容器将不会虚拟出自己的网卡,配置出自己的ip
,而是使用宿主机上的ip
和端口
。也就是说在docker上使用网络和在主机上使用网络是一样的。 - 还有一种网络类型是
None
.也就是没有网络,这种情况docker
将不会和外界的任何东西进行通讯
将nginx
更改到8081端口上访问(实操)
首先把刚才运行的nginx
停掉,然后再指定8081端口
# 关闭docker容器
docker stop containerId
# 指定 nginx端口
docker run -d -p 8081:80 hub.c.163.com/library/nginx
这时就可以看到8081端口正常访问到nginx
了
上面的-p(小写)
是指定端口,而-P(大写)
则是随机分配端口
docker run -d -P hub.c.163.com/library/nginx
docker遇到的问题
- Docker拉取镜像失败报错Get https://registry-1.docker.io/v2/: net/http: request canceled
- Error response from daemon: Get https://index.docker.io/v1/search?q=mysql&n=25: net/http: TLS handshake timeout
- Error response from daemon: Get https://registry-1.docker.io/v2/: net/http: TLS handshake timeout
解决方案
更改daemon.json
,更换镜像源地址
{
"registry-mirrors":["https://6kx4zyno.mirror.aliyuncs.com","http://hub-mirror.c.163.com","https://registry.docker-cn.com"]
}
重启docker
systemctl daemon-reload
systemctl restart docker
- 报错:Error response from daemon:server misbehaving
解决方案
修改DNS
配置文件,增加nameserver
如下
#打开配置文件并进行编辑
vi /etc/resolv.conf
#resolv.conf增加nameserver
nameserver 8.8.4.4
#锁定resolv,防止系统重启被覆盖还原
chattr +i /etc/resolv.conf
#解锁
chattr -i /etc/resolv.conf