1. 容器简介
1.1 什么是Linux容器
容器其实是一种沙盒技术。沙盒像一个集装箱一样把你的应用“装”起来的技术。这样应用与应用之间就因为有了边界而不至于相互干扰;而被装进了集装箱的应用,也可以被方便地搬来搬去。
Linux容器是与系统其他部分隔离开的一系列进程,从另一个镜像运行,并由该镜像提供支持进程所需的全部文件。容器提供的镜像包含了应用的所有依赖项,因而在从开发到测试再到生产的整个过程中,它都具有可移植性和一致性。
1.2 容器简史
容器概念始于 1979 年提出的 UNIX chroot,它是一个 UNIX 操作系统的系统调用,将一个进程及其子进程的根目录改变到文件系统中的一个新位置,让这些进程只能访问到这个新的位置,从而达到了进程隔离的目的。
2000 年的时候 FreeBSD 开发了一个类似于 chroot 的容器技术 Jails,这是最早期,也是功能最多的容器技术。Jails 英译过来是监狱的意思,这个“监狱”(用沙盒更为准确)包含了文件系统、用户、网络、进程等的隔离。
2001 Linux 也发布自己的容器技术 Linux VServer,2004 Solaris 也发布了 Solaris Containers,两者都将资源进行划分,形成一个个 zones,又叫做虚拟服务器。
2005 年推出 OpenVZ,它通过对 Linux 内核进行补丁来提供虚拟化的支持,每个 OpenVZ 容器完整支持了文件系统、用户及用户组、进程、网络、设备和 IPC 对象的隔离。
2007 年 Google 实现了 Control Groups( cgroups ),并加入到 Linux 内核中,这是划时代的,为后期容器的资源配额提供了技术保障。
2008 年基于 cgroups 和 linux namespace 推出了第一个最为完善的 Linux 容器 LXC。
2013 年推出到现在为止最为流行和使用最广泛的容器 Docker,相比其他早期的容器技术,Docker 引入了一整套容器管理的生态系统,包括分层的镜像模型,容器注册库,友好的 Rest API。
2014 年 CoreOS 也推出了一个类似于 Docker 的容器 Rocket,CoreOS 一个更加轻量级的 Linux 操作系统,在安全性上比 Docker 更严格。
2016 年微软也在 Windows 上提供了容器的支持,Docker 可以以原生方式运行在 Windows 上,而不是需要使用 Linux 虚拟机。
基本上到这个时间节点,容器技术就已经很成熟了,再往后就是容器云的发展,由此也衍生出多种容器云的平台管理技术,其中以 kubernetes最为出众,有了这样一些细粒度的容器集群管理技术,也为微服务的发展奠定了基石。因此,对于未来来说,应用的微服务化是一个较大的趋势。
为什么需要容器
其一,这是技术演进的一种创新结果,其二,这是人们追求高效生产活动的一种工具。
随着软件开发的发展,相比于早期的集中式应用部署方式,现在的应用基本都是采用分布式的部署方式,一个应用可能包含多种服务或多个模块,因此多种服务可能部署在多种环境中,如虚拟服务器、公有云、私有云等,由于多种服务之间存在一些依赖关系,所以可能存在应用在运行过程中的动态迁移问题,那这时如何保证不同服务在不同环境中都能平滑的适配,不需要根据环境的不同而去进行相应的定制,就显得尤为重要。
就像货物的运输问题一样,如何将不同的货物放在不同的运输机器上,减少因货物的不同而频繁进行货物的装载和卸载,浪费大量的人力物力。
为此人们发明了集装箱,将货物根据尺寸形状等的不同,用不同规格的集装箱装载,然后再放到运输机上运输,由于集装箱密封,只有货物到达目的地才需拆封,在运输过程能够在不同运输机上平滑过渡,所以避免了资源的浪费。
因此集装箱被誉为是运输业与世界贸易最重要的发明。
Docker 容器的思想就是采用集装箱思想,为应用提供了一个基于容器的标准化运输系统。Docker 可以将任何应用及其依赖打包成一个轻量级、可移植、自包含的容器。容器可以运行在几乎所有的操作系统上。这样容器就可以跑在任何环境中,因此才有了那句话:
Build Once, Run Anywhere
这种集装箱的思想我们也能从 Docker 的 Logo 中看出来,这不就是一堆集装箱吗?
1.3 容器的基本概念
隔离性:容器在操作系统层面提供了进程、文件系统、网络等资源的隔离,确保每个容器内部的操作不会影响到其他容器或主机系统。
轻量级:与虚拟机不同,容器不需要包含整个操作系统,而是共享主机操作系统的内核。因此,容器的启动速度快,占用的资源少。一般容器以毫秒级启动,而虚拟机是分钟级启动。
可移植性:容器镜像包含应用程序及其依赖的所有软件和库,使得容器可以在任何支持容器运行的环境中运行(例如,开发者的本地机器、测试环境、生产环境等)。
Docker系统有两个程序:docker服务端和docker客户端
Docker服务端:是一个服务进程,管理着所有的容器。也叫docker engine
Docker客户端:扮演着docker服务端的远程控制器,可以用来控制docker的服务端进程
docker服务端和客户端运行在一台机器上
Docker三大核心组件:
Docker 仓库 - Docker registery
Docker 镜像 - Docker images
Docker 容器 - Docker containers
1.4 容器的核心技术实现
Namespaces
- 提供进程、网络、文件系统等资源的隔离,确保每个容器内的进程只能看到并操作属于该容器的资源。比如:命名空间可以提供一个进程相互隔离的独立网络空间,不同的容器间进程pid可以相同,进程并不冲突影响,但可以共享底层的计算和存储资源。
Cgroups
- 管理和限制容器使用的资源(如 CPU、内存、磁盘 I/O 等),确保容器不会超出分配的资源。比如给容器A分配4颗CPU,8G 内存,那这个容器最多用这么多的资源。如果内存超过8G ,会启动swap,效率降低,也可能会被调度系统给kill掉。
白话:Namespace的作用是“隔离”,他让应用进程只能“看到”该Namespace内的“世界”;而Cgroups的作用是“限制”,它给这个“世界”围了一圈看不见的“墙”。如此一来,进程就真的被“装”在了一个于是隔绝的“房间”里。这就是所谓的沙盒!
1.5 容器和虚拟机的区别?
传统虚拟技术
虚拟机(virtual machine)就是带环境安装的一种解决方案。
它可以在一种操作系统里面运行另一种操作系统,比如在Windows 系统里面运行Linux 系统。应用程序对此毫无感知,因为虚拟机看上去跟真实系统一模一样,而对于底层系统来说,虚拟机就是一个普通文件,不需要了就删掉,对其他部分毫无影响。这类虚拟机完美的运行了另一套系统,能够使应用程序,操作系统和硬件三者之间的逻辑不变。
虚拟机的缺点:1 资源占用多 2 冗余步骤多 3 启动慢
容器技术
Linux 容器不是模拟一个完整的操作系统,而是对进程进行隔离。有了容器,就可以将软件运行所需的所有资源打包到一个隔离的容器中。容器与虚拟机不同,不需要捆绑一整套操作系统,只需要软件工作所需的库资源和设置。系统因此而变得高效轻量并保证部署在任何环境中的软件都能始终如一地运行。
Docker和传统虚拟化方式的不同之处:
传统虚拟机技术是虚拟出一套硬件后,在其上运行一个完整操作系统,在该系统上再运行所需应用进程;而容器内的应用进程直接运行于宿主的内核,容器内没有自己的内核,而且也没有进行硬件虚拟。因此容器要比传统虚拟机更为轻便。每个容器之间互相隔离,每个容器有自己的文件系统 ,容器之间进程不会相互影响,能区分计算资源。
为什么docker比VM快?
docker有着比虚拟机更少的抽象层。由于docker不需要Hypervisor(虚拟机监视器,管理资源的)实现硬件资源虚拟化,运行在docker容器上的程序直接使用的都是实际物理机的硬件资源。因此在CPU、内存利用率上docker将会在效率上有明显优势。
docker利用的是宿主机的内核,而不需要Guest OS(访客系统|虚拟系统)。因此,当新建一个容器时,docker不需要和虚拟机一样重新加载一个操作系统内核。避免引寻、加载操作系统内核比较费时费资源的过程,当新建一个虚拟机时,虚拟机软件需要加载Guest OS,这个新建过程是分钟级别的。而docker由于直接利用宿主机的操作系统,则省略了这个过程,因此新建一个docker容器只需要几秒钟。
2. Docker简介
2.1 Docker是什么
官网:
开发人员通过Docker将他们的想法变为现实
将软件打包为标准化单元,用于开发、装运和部署
容器是一个标准的软件单元,它封装代码及其所有依赖项,以便应用程序从一个计算环境快速可靠地运行到另一个环境。Docker容器镜像是一个轻量级、独立的可执行软件包,包括运行应用程序所需的一切:代码、运行时、系统工具、系统库和设置。
容器镜像在运行时会变成容器,在Docker容器的情况下,镜像在Docker引擎上运行时会成为容器。容器化软件可用于基于Linux和Windows的应用程序,无论基础结构如何,都将始终运行相同的软件。容器将软件与其环境隔离开来,并确保它统一工作,尽管存在差异,例如开发和阶段之间的差异。
2013年,Docker推出了集装箱行业标准。容器是一个标准化的软件单元,允许开发人员将应用程序与其环境隔离,解决“它在我的机器上工作”的难题。对于今天数以百万计的开发人员来说,Docker是构建和共享容器化应用程序的事实标准——从桌面到云。我们正在为开发人员和开发团队构建从代码到云的独特连接体验。
2.2 Docker的目标
docker的主要目标是"Build Once, Run Anywhere", 构建,运输,处处运行
- 构建:做一个docker镜像
- 运输:docker pull or push
- 运行:启动一个容器
每一个容器,他都有自己的文件系统rootfs.
2.3 有容器&&没容器
没有容器的时候:
1.rd开发产品(需要配置开发环境)LAMP=Linux+Apache+Mysql+Php
2.测试(需要配置测试环境)LAMP=Linux+Apache+Mysql+Php
3.op上线(需要线上/生产环境)LAMP=Linux+Apache+Mysql+Php
有容器之后:
-
rd开发产品(需要在docker容器里配置开发环境)LAMP=Linux+Apache+Mysql+Php
-
把容器打包成镜像交给运维,运维上线。
Docker跟原有的工具区别:
- 传统的部署模式是:安装(包管理工具或者源码包编译)->配置->运行;
- Docker的部署模式是:复制->运行。
复制代码
Docker对服务器端开发/部署带来的变化:
- 方便快速部署
- 对于部署来说可以极大的减少部署的时间成本和人力成本
- Docker支持将应用打包进一个可以移植的容器中,重新定义了应用开发,测试,部署上线的过程,核心理念是 Build once, Run anywhere(一次构建,多次部署)
- 1)标准化应用发布,docker容器包含了运行环境和可执行程序,可以跨平台和主机使用;
- 2)节约时间,快速部署和启动,VM启动一般是分钟级,docker容器启动是秒级;
- 3)方便构建基于微服务架构的系统,通过服务编排,更好的松耦合(解耦);
- 4)节约成本,以前一个虚拟机至少需要几个G的磁盘空间,docker容器可以减少到MB级;
复制代码
- Docker Client(Docker 客户端)
Docker 客户端是用户与 Docker 系统交互的接口。用户通过 CLI 命令(如 docker run、docker build)与 Docker 守护进程通信,发出管理容器的各种指令。
- Dockerd(Docker 守护进程)
Dockerd 是 Docker 的核心守护进程,负责处理来自 Docker 客户端的请求。它管理 Docker 容器、镜像、网络和数据卷,并将请求传递给下一级组件(如 Containerd)。通过 gRPC 与 Containerd 通信。
- Containerd
Containerd 是一个高级容器运行时,负责管理容器的整个生命周期。它处理容器的创建、执行、挂载存储和网络管理。通过 gRPC 接收 Dockerd 的指令,并进一步传递给 Runc 和 Shim。
- Runc
Runc 是一个 CLI 工具,用于根据 Open Container Initiative (OCI) 规范创建和运行容器。Runc 实际上负责执行容器的启动、停止等底层操作。它通过 fork 进程来创建容器。
- Shim
Shim 是一个中介程序,在容器与 Containerd 之间提供隔离。当 Runc 启动容器后,Shim 保持容器运行并将 Runc 从系统进程中分离。这样,如果 Containerd 需要重启或崩溃,容器仍然可以继续运行。
3. Docker安装
CentOS 7 中 Docker 的安装:
Docker 软件包已经包括在默认的 CentOS-Extras 软件源(联网使用centos7u2自带网络Yum源)里。因此想要安装 docker,只需要运行下面的 yum 命令:
- # yum install -y epel-release
- # yum install docker -y #docker 1.13版本
- 启动 Docker 服务:
- CentOS 6
- # service docker start
- # chkconfig docker on
- CentOS 7
- # systemctl start docker.service
- # systemctl enable docker.service
复制代码
确定docker服务在运行:
结果会显示服务端和客户端的版本,如果只显示客户端版本说明服务没有启动
- # docker version
- Client:
- Version: 1.10.3
- API version: 1.22
- ...
- docker -v
复制代码
Docker版本与官方安装方式
moby、docker-ce与docker-ee
最早时docker是一个开源项目,主要由docker公司维护。
2017年3月1日起,docker公司将原先的docker项目改名为moby,并创建了docker-ce和docker-ee。
三者关系:
- moby是继承了原先的docker的项目,是社区维护的的开源项目,谁都可以在moby的基础打造自己的容器产品
- docker-ce是docker公司维护的开源项目,是一个基于moby项目的免费的容器产品
- docker-ee是docker公司维护的闭源产品,是docker公司的商业产品
复制代码
moby project由社区维护,docker-ce project是docker公司维护,docker-ee是闭源的docker公司维护。
CentOS–官方安装
Docker官网:https://www.docker.com/
- 如果是centos,上面的安装命令会在系统上添加yum源:/etc/yum.repos.d/docker-ce.repo
- # wget https://download.docker.com/linux/centos/docker-ce.repo
- # mv docker-ce.repo /etc/yum.repos.d
- # yum install -y docker-ce
复制代码
或者直接下载rpm安装:
- # wget https://download.docker.com/linux/centos/7/x86_64/stable/Packages/docker-ce-17.09.0.ce-1.el7.centos.x86_64.rpm
- # rpm -ivh docker-ce-17.09.0.ce-1.el7.centos.x86_64.rpm --nodeps --force
复制代码
3.1 国内源安装docker
使用aliyun docker yum源安装新版docker
删除已安装的Docker
- [root@docker-server ~]# 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 Yum源
阿里云镜像源地址:mirrors.aliyun.com
- # yum install -y yum-utils
- # yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
复制代码
安装指定版本
- 查看Docker版本:
- # yum list docker-ce --showduplicates
复制代码
安装较旧版本(比如Docker 17.03.2) :
需要指定完整的rpm包的包名,并且加上–setopt=obsoletes=0 禁止自动更新参数:
- # yum install -y --setopt=obsoletes=0 \
- docker-ce-17.03.2.ce-1.el7.centos.x86_64 \
- docker-ce-selinux-17.03.2.ce-1.el7.centos.noarch
- 例如:
- # yum install -y --setopt=obsoletes=0 docker-ce-19.03.2 docker-ce-selinux-19.03.2
复制代码
安装Docker最新版:加上rpm包名的版本号部分或不加都可以:
- [root@docker-server ~]# yum install -y docker-ce #默认安装的是最新版本
复制代码
启动Docker服务:
- #systemctl enable docker
- #systemctl start docker
复制代码
查看docker版本状态:
- [root@docker-server ~]# docker -v
- Docker version 20.10.21, build baeda1f
复制代码- [root@docker-server ~]# docker version
- Client: Docker Engine - Community
- Version: 20.10.21
- API version: 1.41
- Go version: go1.18.7
- Git commit: baeda1f
- Built: Tue Oct 25 18:04:24 2022
- OS/Arch: linux/amd64
- Context: default
- Experimental: true
- Server: Docker Engine - Community
- Engine:
- Version: 20.10.21
- API version: 1.41 (minimum version 1.12)
- Go version: go1.18.7
- Git commit: 3056208
- Built: Tue Oct 25 18:02:38 2022
- OS/Arch: linux/amd64
- Experimental: false
- containerd:
- Version: 1.6.9
- GitCommit: 1c90a442489720eec95342e1789ee8a5e1b9536f
- runc:
- Version: 1.1.4
- GitCommit: v1.1.4-0-g5fd4c4d
- docker-init:
- Version: 0.19.0
- GitCommit: de40ad0
- Version: 0.19.0
- GitCommit: de40ad0
复制代码
查看docker运行状态:
- # docker info
- Containers: 0
- Running: 0
- Paused: 0
- Stopped: 0
- Images: 0
- ...
复制代码
=======================================================
简单测试
Docker官网镜像网站:https://hub.docker.com/
查看镜像
docker images
查看容器(正在运行的容器):
docker ps
查看所有容器
docker ps -a
- 运行一个容器
- 拉取镜像:docker pull +镜像地址
- [root@192 ~]# docker run -it daocloud.io/library/ubuntu /bin/bash #运行容器
- Unable to find image 'daocloud.io/library/ubuntu:latest' locally
- latest: Pulling from library/ubuntu
- 5c939e3a4d10: Pull complete
- c63719cdbe7a: Pull complete
- 19a861ea6baf: Pull complete
- 651c9d2d6c4f: Pull complete
- Digest: sha256:bc025862c3e8ec4a8754ea4756e33da6c41cba38330d7e324abd25c8e0b93300
- Status: Downloaded newer image for daocloud.io/library/ubuntu:latest
- 如果自动进入下面的容器环境,说明ubuntu镜像运行成功,Docker的安装也没有问题:可以操作容器了
- root@db8e84e2ea96:/#
复制代码
**Docker 加速器 **
- 使用 Docker 的时候,需要经常从官方获取镜像,但是由于显而易见的网络原因,拉取镜像的过程非常耗时,严重影响使用 Docker 的体验。因此 DaoCloud 推出了加速器工具解决这个难题,通过智能路由和缓存机制,极大提升了国内网络访问 Docker Hub 的速度。
- Docker 加速器对 Docker 的版本有要求吗?
- 需要 Docker 1.8 或更高版本才能使用。
- Docker 加速器支持什么系统?
- Linux, MacOS 以及 Windows 平台。
- Docker 加速器是否收费?
- 提供永久免费的加速器服务,请放心使用。
复制代码
打开/etc/docker/daemon.json添加如下内容后,重启docker生效
{
“registry-mirrors”: [
“http://hub-mirror.c.163.com”,
“https://docker.m.daocloud.io”,
“https://dockerproxy.com”,
“https://docker.mirrors.ustc.edu.cn”,
“https://docker.nju.edu.cn”
]
}
3.2 daocloud国内镜像市场
使用国内镜像:
进入网站:https://daocloud.io/
https://dashboard.daocloud.io/
https://hub.atomgit.com/
进入镜像市场
随便选择一个,选择mysql
上面有详细的使用命令。但是每个镜像的命令不一样,在选择一个:
- [root@docker-server ~]# docker pull daocloud.io/library/nginx #下载镜像
- Using default tag: latest
- latest: Pulling from library/nginx
- 0a4690c5d889: Pull complete
- 9719afee3eb7: Pull complete
- 44446b456159: Pull complete
- Digest: sha256:f83b2ffd963ac911f9e638184c8d580cc1f3139d5c8c33c87c3fb90aebdebf76
- Status: Downloaded newer image for daocloud.io/library/nginx:latest
- daocloud.io/library/nginx:latest
复制代码
3.3 阿里云容器镜像服务
配置阿里云的镜像仓库
创建阿里云的公开仓库
公开:在拉取的时候,不需要输入用户名和密码。推送仍然需要输入用户名和密码;
私有:拉取,推送都需要输入用户名和密码;
- [root@docker ~]# docker login --username=runfast520 registry.cn-hangzhou.aliyuncs.com
- [root@docker ~]# docker tag mysql:8.0 registry.cn-hangzhou.aliyuncs.com/cloud2204/mysql:8.0
- [root@docker ~]# docker push registry.cn-hangzhou.aliyuncs.com/cloud2204/mysql:8.0
复制代码
上传成功之后:
使用自己的私有仓库
- [root@coding-start ~]# docker login --username=youngfit --password='***' registry.cn-hangzhou.aliyuncs.com
- [root@coding-start ~]# docker tag daocloud.io/library/nginx:1.12.0-alpine registry.cn-hangzhou.aliyuncs.com/cloud2204/nginx:1.12
- [root@coding-start ~]# docker push registry.cn-hangzhou.aliyuncs.com/cloud2204/nginx:1.12
- 退出登录状态:
- docker logout registry.cn-hangzhou.aliyuncs.com
复制代码
查看上传的镜像
自己的nginx:1.12版本已经上传成功!
阿里云的镜像加速器
- 配置阿里加速器:
- 如果这个目录/etc/docker/不存在就创建
- [root@docker-server ~]# vim /etc/docker/daemon.json
- {
- "registry-mirrors": ["https://ukblsmil.mirror.aliyuncs.com"]
- }
- [root@docker-server ~]# systemctl daemon-reload
- [root@docker-server ~]# systemctl restart docker
复制代码
3.4 腾讯云容器镜像服务
注册账号–>登录–>搜索“容器镜像服务”
创建命名空间
创建仓库
使用指南
- # 登录1
- [root@docker-server1 ~]# docker login ccr.ccs.tencentyun.com --username=100003726264
- Password: syf_****** #这里直接填写用户名的密码即可
- # 登录2
- [root@docker-server1 ~]# docker login ccr.ccs.tencentyun.com --username=100003726264 --password=syf_*** #这里直接填写用户名的密码即可
复制代码
推送镜像
- [root@docker-server1 ~]# docker tag daocloud.io/library/mysql:5.7.5-m15 ccr.ccs.tencentyun.com/youngfit/mysql:5.7
- [root@docker-server1 ~]# docker push ccr.ccs.tencentyun.com/youngfit/mysql:5.7
复制代码
拉取镜像
- # 先删除之前的镜像
- [root@docker-server1 ~]# docker rmi ccr.ccs.tencentyun.com/youngfit/mysql:5.7 daocloud.io/library/mysql:5.7.5-m15
- # 拉取
- [root@docker-server1 ~]# docker pull ccr.ccs.tencentyun.com/youngfit/mysql:5.7
复制代码
- # 使用镜像
- [root@docker-server1 ~]# docker run -d --name some-mysql -e MYSQL_ROOT_PASSWORD=FeiGe@520 ccr.ccs.tencentyun.com/youngfit/mysql:5.7
- [root@docker-server1 ~]# mysql -uroot -p'FeiGe@520' -h 172.17.0.2
复制代码
4. Docker镜像
Docker 镜像
Docker 镜像是 Docker 容器运行时的只读模板,每一个镜像由一系列的层 (layers) 组成。Docker 使用 UnionFS 来将这些层联合到单独的镜像中。正因为有了这些层的存在,Docker 是如此的轻量。当你改变了一个 Docker 镜像,比如升级到某个程序到新的版本,一个新的层会被创建。因此,不用替换整个原先的镜像或者重新建立(在使用虚拟机的时候你可能会这么做),只是一个新的层被添加或升级了。
在 Docker 的术语里,一个只读层被称为镜像,一个镜像是永久不会变的。由于 Docker 使用一个统一文件系统,由于镜像不可写,所以镜像是无状态的。
- 镜像由三部分组成:
- 镜像名称:仓库名称+镜像分类+tag名称(镜像版本)
- 1.存储对象:images
- 2.格式:库名/分类:tag
- 3.tag:表示镜像版本
复制代码
镜像的大体分类方式:这不是规定
- 1.以操作系统名字
- centos的docker镜像:
- centos5
- centos6
- centos7
- -----------------
复制代码- 2.以应用的名字
- nginx的docker镜像
- tomcat的docker镜像
- mysql的docker镜像
复制代码
镜像名字:
- 完整镜像名称示例:
- docker.io/library/nginx:v1
- docker.io/library/nginx:latest
- daocloud.io/library/nginx
复制代码
镜像ID:
所有镜像都是通过一个 64 位十六进制字符串来标识的。 为简化使用,前 12 个字符可以组成一个短ID,可以在命令行中使用。短ID还是有一定的碰撞机率,所以服务器总是返回长ID。
镜像ID:64位的id号,一般我们看到的是12位的我们称之为短ID,只要我们每个ID号不冲突就可以了
- 镜像本身:是由一层一层的镜像合在一起的,最底层的镜像我们称为基础镜像,在这个基础镜像的基础上还可以在做镜像,在做的镜像称为子镜像,对于子镜像来讲在谁的基础之上做的就是父镜像。
- 基础镜像:一个没有任何父镜像的镜像,谓之基础镜像。
- centos7 镜像
- centos7+nginx 镜像
复制代码
Docker 容器
Docker 容器和文件夹很类似,一个Docker容器包含了所有的某个应用运行所需要的环境。每一个 Docker 容器都是从 Docker 镜像创建的。Docker 容器可以运行、启动、停止、移动、删除、暂停(挂起)。每一个 Docker 容器都是独立和安全的应用平台,Docker 容器是 Docker 的运行一部分。
4.1 Docker镜像命名解析
Docker镜像命名解析
镜像是Docker最核心的技术之一,也是应用发布的标准格式。无论你是用docker pull image,或者是Dockerfile里面写FROM image,从Docker官方Registry下载镜像应该是Docker操作里面最频繁的动作之一了。那么docker镜像是如何命名的,这也是Docker里面比较容易令人混淆的一块概念:Registry,Repository, Tag and Image。
那么Registry又是什么呢?Registry存储镜像数据,并且提供拉取和上传镜像的功能。Registry中镜像是通过Repository来组织的,而每个Repository又包含了若干个Image。
下面是在本地机器运行docker images的输出结果:
常说的"ubuntu"镜像其实不是一个镜像名称,而是代表了一个名为ubuntu的Repository,同时在这个Repository下面有一系列打了tag的Image,Image的标记是一个GUID,为了方便也可以通过Repository:tag来引用。
Image[:tag]
当一个镜像的名称不足以分辨这个镜像所代表的含义时,你可以通过tag将版本信息添加到run命令中,以执行特定版本的镜像。
- 例如:docker run ubuntu:14.04
复制代码
4.2 Docker镜像和容器的区别
一、Docker镜像
一个Docker镜像可以构建于另一个Docker镜像之上,这种层叠关系可以是多层的。第1层的镜像层我们称之为基础镜像(Base Image),其他层的镜像(除了最顶层)我们称之为父层镜像(Parent Image)。这些镜像继承了他们的父层镜像的所有属性和设置。
Docker镜像通过镜像ID进行识别。镜像ID是一个64字符的十六进制的字符串。但是当我们运行镜像时,通常我们不会使用镜像ID来引用镜像,而是使用镜像名来引用。
要列出本地所有有效的镜像,可以使用命令
- # docker images
- # docker image list
复制代码
镜像可以发布为不同的版本,这种机制我们称之为标签(Tag)。
可以使用pull命令加上指定的标签(不加版本号默认是最新版本):
- # docker pull ubuntu:11
- # docker pull ubuntu:12.04
- # docker pull centos:7
复制代码
二、Docker容器
Docker容器可以使用命令创建:
- # docker run -it imagename /bin/bash
复制代码
它会在所有的镜像层之上增加一个可写层。这个可写层有运行在CPU上的进程,而且有两个不同的状态:运行态(Running)和退出态 (Exited)挂起状态。这就是Docker容器。当我们使用docker run启动容器,Docker容器就进入运行态,当我们停止Docker容器时,它就进入退出状态。
当我们有一个正在运行的Docker容器时,从运行态到停止态,我们对它所做的一切变更都会永久地写到容器的文件系统中。要切记,对容器的变更是写入到容器的文件系统的,而不是写入到Docker镜像中的。我们可以用同一个镜像启动多个Docker容器,这些容器启动后都是活动的,彼此还是相互隔离的。我们对其中一个容器所做的变更只会局限于那个容器本身。如果对容器的底层镜像进行修改,那么当前正在运行的容器是不受影响的,不会发生自动更新现象。
4.3 镜像管理
- 这种方法只能用于官方镜像库
- 搜索基于 centos 操作系统的镜像
- [root@docker-server ~]# docker search centos
复制代码
按星级搜索镜像:
- 查找 star 数至少为 100 的镜像,默认不加 s 选项找出所有相关 centos 镜像:
- [root@docker-server ~]# docker search ubuntu -f stars=100
复制代码
拉取镜像:
- # docker pull centos
- 注:没有加registry,默认是从docker.io/dockerhub下载的
- [root@docker-server ~]# docker pull daocloud.io/library/tomcat:7
- [root@docker-server ~]# docker pull daocloud.io/library/centos:6
复制代码
查看本地镜像:
- [root@docker-server ~]# docker image list
- 或者
- [root@docker-server ~]# docker images
复制代码
查看镜像详情:
- [root@docker-server ~]# docker inspect 镜像id/镜像名称
复制代码
删除镜像:
- 删除一个或多个,多个之间用空格隔开,可以使用镜像名称或id
- [root@docker-server ~]# docker rmi daocloud.io/library/mysql
- 或者
- [root@docker-server ~]# docker rmi 81debc
- 或者
- docker image rm 镜像名或者镜像id
- 参数解释:
- rm Remove one or more containers ---移除一个或多个容器
- rmi Remove one or more images ---删除一个或多个镜像
复制代码
强制删除:–force
- 如果镜像正在被使用中可以使用--force强制删除
- # docker rmi docker.io/ubuntu:latest --force
- -f, --force Force removal of the image
- 注意: 容器运行中不能删除,将容器停止后,删除容器,再删除镜像。
复制代码
只查看所有镜像的id:
- [root@docker-server ~]# docker images -q
- 98ebf73aba75
- 81debc95563d
- d0957ffdf8a2
- -q, --quiet
复制代码
删除所有镜像:
- [root@docker-server ~]# docker rmi $(docker images -q)
- 或者docker rmi `docker images -q`
复制代码
查看镜像制作的过程:
相当于dockfile
- [root@docker-server ~]# docker history daocloud.io/library/nginx 使用镜像名或者镜像ID都可以
复制代码
5. 容器管理
5.1 容器基本操作
5.1.1 启动容器
创建新容器但不启动:
- [root@docker-server ~]# docker create -it daocloud.io/library/centos:7 /bin/bash
复制代码
创建并运行一个新Docker 容器:同一个镜像可以启动多个容器,每次执行run子命令都会运行一个全新的容器
- [root@docker-server ~]# docker run -it --restart=always daocloud.io/library/centos:7 /bin/bash #最常用
- -i:标准输入输出
- -t:分配一个终端或控制台
- --restart=always:容器随docker engine自启动,因为在重启docker的时候默认容器都会被关闭
- 也适用于create选项
- -d 后台运行容器,并返回容器ID
复制代码
如果执行成功,说明CentOS 容器已经被启动,并且应该已经得到了 bash 提示符。
- --rm:默认情况下,每个容器在退出时,它的文件系统也会保存下来.另一方面,也可以保存容器所产生的数据。但是当你仅仅需要短暂的运行一个容器,并且这些数据不需要保存,你可能就希望Docker能在容器结束时自动清理其所产生的数据。这个时候就需要--rm参数了。
- 示例:
- [root@docker-server ~]# docker run -it --rm daocloud.io/library/nginx:latest /bin/bash
- root@be2d0a462ce1:/# exit
- exit
- 注意:不能用-d , --rm和--restart=alwarys冲突;
- [root@docker-server ~]# docker ps -a
- CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
复制代码
容器名称
- 为容器分配一个名字,如果没有指定,docker会自动分配一个随机名称是 docker run 子命令的参数
- --name= Assign a name to the container
- # docker run -it --name 名字 daocloud.io/centos:6 /bin/bash #名字自定义
复制代码
如果你在执行docker run时没有指定–name,那么自动生成一个随机字符串UUID。这个UUID标识是由Docker deamon生成的。但是对于一个容器来说有个name会非常方便,当你需要连接其它容器时或者类似需要区分其它容器时,使用容器名称可以简化操作。无论容器运行在前台或者后台,这个名字都是有效的。
若要断开与容器的连接,并且关闭容器:容器内部执行如下命令
- root@37b8b8cdd75f:/# exit
复制代码
如果只想断开和容器的连接而不关闭容器:
5.1.2 查看容器:
- 1.只查看运行状态的容器:
- # docker ps
- 2.-a 查看所有容器
- # docker ps -a
- 3.只查看所有容器id:
- # docker ps -a -q
- 或者docker ps -qa
复制代码
5.1.3 查看容器详细信息:
inspect :用于查看容器的配置信息,包含容器名、环境变量、运行命令、主机配置、网络配置和数据卷配置等。
目标:查找某一个运行中容器的id,然后使用docker inspect命令查看容器的信息。
提示:可以使用容器id的前面部分,不需要完整的id。
- [root@docker-server ~]# docker inspect 容器名称/容器ID #机器上运行的一个容器ID或者名称
- [
- {
- "Id": "d95a220a498e352cbfbc098c949fc528dbf5a5c911710b108ea3a9b4aa3a4761",
- "Created": "2017-07-08T03:59:16.18225183Z",
- "Path": "bash",
- "Args": [],
- "State": {
- "Status": "exited",
- "Running": false,
- "Paused": false,
- "Restarting": false,
- "OOMKilled": false,
- "Dead": false,
- "Pid": 0,
- 容器信息很多,这里只粘贴了一部分
复制代码
5.1.4 启动容器:
- # docker start name #容器ID也可以
- 这里的名字是状态里面NAMES列列出的名字,这种方式同样会让容器运行在后台
复制代码
5.1.5 关闭容器:
- # docker stop name
- # docker kill name --强制终止容器
复制代码
5.1.6 杀死所有running状态的容器
- # docker kill $(docker ps -q)
- # docker stop `docker ps -q`
复制代码
5.1.7 stop和kill的区别:
docker stop命令给容器中的进程发送SIGTERM信号,默认行为是会导致容器退出,当然,容器内程序可以捕获该信号并自行处理,例如可以选择忽略。而docker kill则是给容器的进程发送SIGKILL信号,该信号将会使容器必然退出。
5.1.8 删除容器:
- # docker rm 容器id或名称
- 要删除一个运行中的容器,添加 -f 参数 --慎用。先stop在删除
复制代码
根据格式删除所有容器:
- # docker rm $(docker ps -qf status=exited)
- -f:过滤
- pause :暂停容器中所有的进程(挂起)
- unpause:恢复容器内暂停的进程,与pause对应
- [root@docker-server ~]# docker pause 容器名
- [root@docker-server ~]# docker ps
- CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
- 3c0e0f43807d 98ebf73aba "/bin/bash" 7 minutes ago Up 7 minutes (Paused) 80/tcp c7
- [root@docker-server ~]# docker unpause 容器名 #恢复
复制代码
重启容器:
- [root@docker-server ~]# docker restart name
复制代码
让容器运行在后台:
- # docker run -dit 镜像ID /bin/bash
- -d 后台运行必须要加-it
复制代码
如果在docker run后面追加-d=true或者-d,那么容器将会运行在后台模式。此时所有I/O数据只能通过网络资源或者共享卷组来进行交互。因为容器不再监听你执行docker run的这个终端命令行窗口。
注:
容器运行在后台模式下,是不能使用–rm选项的(老版本是这样,新版本已经可以同时生效)
5.1.9 修改容器名字
rename —修改容器名称
- [root@docker-server ~]# docker rename mytest testmy
- [root@docker-server ~]# docker ps -a
- CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
- 774c02898fb1 daocloud.io/library/nginx "/bin/bash -c 'while…" 5 minutes ago Up About a minute 80/tcp testmy
复制代码
5.1.10 查看容器资源情况
stats
显示容器资源使用统计信息的实时流
- [root@docker-server ~]# docker stats
- --当有容器在运行的时候动态显示容器的资源消耗情况,包括:CPU、内存、网络I/O
复制代码
5.1.11 登陆容器方法
连接容器:前提是容器在运行状态中
方法1.attach
- # docker attach 容器id #前提是容器创建时必须指定了交互shell
复制代码
方法2.exec
通过exec命令可以创建两种任务:后台型任务和交互型任务
- 1.交互型任务:
- [root@docker-server ~]# docker exec -it 容器id /bin/bash
- root@68656158eb8e:/# ls
- 2.后台型任务:不进入容器里面执行命令
- [root@docker-server ~]# docker exec 容器id touch /testfile
复制代码
监控容器的运行:
可以使用logs、top、wait这些子命令
logs:使用logs命令查看守护式容器
可以通过使用docker logs命令来查看容器的运行日志,其中–tail选项可以指定查看最后几条日志,使用-f选项可以跟踪日志的输出,直到手动停止。
- [root@docker-server ~]# docker pull daocloud.io/library/nginx
- [root@docker-server ~]# docker images
- [root@docker-server ~]# docker run -it --name nginx1 98ebf73
- root@8459191dbe7c:/# /usr/sbin/nginx #启动nginx
- ctrl+p+q --- 退出
- [root@docker-server ~]# docker inspect nginx1 #找到ip地址
- [root@docker-server ~]# curl -I http://172.17.0.3 #宿主机访问容器可以访问成功
- HTTP/1.1 200 OK
- Server: nginx/1.17.1
- Date: Mon, 09 Mar 2020 14:49:40 GMT
- Content-Type: text/html
- Content-Length: 612
- Last-Modified: Tue, 25 Jun 2019 12:19:45 GMT
- Connection: keep-alive
- ETag: "5d121161-264"
- Accept-Ranges: bytes
- [root@docker-server ~]# curl -I http://172.17.0.3 #继续测试访问
- 在开启一个终端:
- [root@docker-server ~]# docker logs -f nginx1
- root@8459191dbe7c:/# /usr/sbin/nginx
- root@8459191dbe7c:/# 172.17.0.1 - - [09/Mar/2020:14:49:33 +0000] "HEAD / HTTP/1.1" 200 0 "-" "curl/7.29.0" "-"
- 172.17.0.1 - - [09/Mar/2020:14:49:40 +0000] "HEAD / HTTP/1.1" 200 0 "-" "curl/7.29.0" "-"
复制代码
top:显示一个运行的容器里面的进程信息
- [root@docker-server ~]# docker top nginx #容器ID也可以
复制代码
wait :–捕捉容器停止时的退出码
执行此命令后,该命令会"hang"在当前终端,直到容器停止,此时,会打印出容器的退出码
- 在第一个终端执行停止容器命令
- [root@docker-server ~]# docker stop nginx1
- =============================================================================
- [root@docker-server ~]# docker wait nginx1 #第二个终端操作
- 0
- docker run 之后容器退出的状态码:
- 0,表示正常退出
- 非0,表示异常退出(退出状态码采用chroot标准)
- 125,Docker守护进程本身的错误
- 126,容器启动后,要执行的默认命令无法调用
- 127,容器启动后,要执行的默认命令不存在
复制代码
5.1.12 宿主机和容器之间相互拷贝文件/目录
cp的用法如下:
- Usage:
- docker cp [OPTIONS] CONTAINER:PATH LOCALPATH --从容器拷贝到本机
- docker cp [OPTIONS] LOCALPATH CONTAINER:PATH --从本机拷贝到容器
复制代码
如:容器nginx中/usr/local/bin/存在test.sh文件,可如下方式copy到宿主机
- [root@docker-server ~]# docker run -it --name mytest nginx:latest /bin/bash
- root@2a9a18b4a485:/# cd /usr/local/bin/
- root@2a9a18b4a485:/usr/local/bin# touch test.sh
- ctrl+p+q 退出
- [root@docker-server ~]# docker cp mytest:/usr/local/bin/test.sh /root/
复制代码
修改完毕后,将该文件重新copy回容器
- [root@docker-server ~]# ls
- anaconda-ks.cfg test.sh
- [root@docker-server ~]# echo "123" >> test.sh
- [root@docker-server ~]# docker cp /root/test.sh mytest:/usr/local/bin/
- [root@docker-server ~]# docker cp -a /opt mytest:/usr/local/bin/ #拷贝目录
复制代码
5.1.13 容器的状态
Created:
- 容器已经被创建,但尚未启动。此时,容器处于一种待机状态,等待进一步的操作。
Running:
- 容器正在运行并执行其主要进程。处于此状态的容器可以处理请求和数据。
- docker ps 可以显示所有正在运行的容器。
Paused:
- 容器的所有进程被暂停(挂起)。此时,容器的 CPU 资源被释放,但内存等其他资源仍然占用。
- 你可以通过 docker pause 暂停一个容器,并通过 docker unpause 恢复它。
Restarting:
- 容器正在重新启动。通常,这种情况发生在容器配置了自动重启策略时,其进程由于某种原因终止并触发重启。
Exited:
- 容器的主进程已经停止运行,并且没有自动重启策略,或者重启策略未能触发。容器退出状态码可以通过 docker inspect 命令查看。
- docker ps -a 可以显示所有包含已退出容器的列表。
Dead:
- 容器遇到严重问题,无法恢复。通常,这是 Docker 容器处于崩溃状态的标志,需要人工干预来处理这个容器。
5.2. 端口映射
使用端口映射解决容器端口访问问题
- -p:创建应用容器的时候,一般会做端口映射,这样是为了让外部能够访问这些容器里的应用。可以用多个-p指定多个端口映射关系。
复制代码
mysql应用端口转发:
查看本地地址:
- [root@docker-server ~]# ip a
- ...
- 2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
- link/ether 00:0c:29:9c:bf:66 brd ff:ff:ff:ff:ff:ff
- inet 192.168.246.141/24 brd 192.168.246.255 scope global dynamic ens33
- valid_lft 5217593sec preferred_lft 5217593sec
- inet6 fe80::a541:d470:4d9a:bc29/64 scope link
- valid_lft forever preferred_lft forever
复制代码
运行容器:使用-p作端口转发,把本地3307转发到容器的3306,其他参数需要查看发布容器的页面提示
- [root@docker-server ~]# docker pull daocloud.io/library/mysql:5.7
- [root@docker-server ~]# docker run -d --name mysql1 -p 3307:3306 -e MYSQL_ROOT_PASSWORD=Qf@123! daocloud.io/library/mysql:5.7
- -e MYSQL_ROOT_PASSWORD= 设置环境变量,这里是设置mysql的root用户的密码
复制代码
通过本地IP:192.168.246.141的3307端口访问容器mysql1内的数据库,出现如下提示恭喜你
- 1.安装一个mysql客户端
- [root@docker-server ~]# yum install -y mysql
- 2.登录
- [root@docker-server ~]# mysql -uroot -p'Qf@123!' -h 192.168.246.141 -P 3307
- Welcome to the MariaDB monitor. Commands end with ; or \g.
- Your MySQL connection id is 3
- Server version: 5.7.26 MySQL Community Server (GPL)
- Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.
- Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
- MySQL [(none)]>
复制代码- -P(大P):当使用-P标记时,Docker 会随机映射一个 32768~49900 的端口到内部容器开放的网络端口。如下:
- [root@docker-server ~]# docker pull daocloud.io/library/redis
- [root@docker-server ~]# docker images
- REPOSITORY TAG IMAGE ID CREATED SIZE
- daocloud.io/library/redis latest 598a6f110d01 2months ago 118MB
- [root@docker-server ~]# docker run -d --name myredis -P daocloud.io/library/redis
- ca06a026d84a0605d9a9ce6975389a79f4ab9a9a043a03f088cd909c1fe52e29
- [root@docker-server ~]# docker ps
- CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
- ca06a026d84a daocloud.io/library/redis "docker-entrypoint.s…" 22 seconds ago Up 21 seconds 0.0.0.0:32768->6379/tcp myredis
复制代码
从上面的结果中可以看出,本地主机的32768端口被映射到了redis容器的6379端口上,也就是说访问本机的32768端口即可访问容器内redis端口。
在别的机器上通过上面映射的端口32768连接这个容器的redis
- [root@docker-server2 ~]# yum install -y redis
- [root@docker-server2 ~]# redis-cli -h 192.168.246.141 -p 32768
- 192.168.246.141:32768> ping
- PONG
复制代码
5.3. docker数据卷
- 把本地宿主机上面的某一个目录挂载到容器里面的目录去。这两个目录都不用提前存在,会自动创建。
复制代码
新卷只能在容器创建过程当中挂载
- [root@docker-server ~]# docker run -it --name testnginx -v /test:/test2 daocloud.io/library/nginx /bin/bash
- root@86320e734cd1:/# ls
- root@86320e734cd1:/# ctrl+p+q #退出 ·
- 测试:
- [root@docker-server ~]# cd /test/
- [root@docker-server test]# ls
- [root@docker-server test]# touch a.txt
- [root@docker-server test]# cd
- [root@docker-server ~]# docker exec -it testnginx /bin/bash
- root@86320e734cd1:/# cd test2/
- root@86320e734cd1:/test2# ls
- a.txt
- 共享文件:
- [root@docker-server ~]# mkdir /dir
- [root@docker-server ~]# vim /dir/a.txt
- 123
- [root@docker-server ~]# docker run -it --name testnginx2 -v /dir/a.txt:/dir1/a.txt daocloud.io/library/nginx /bin/bash
- root@f899be627552:/# cat dir1/a.txt
- 123
复制代码
共享其他容器的卷(其他容器用同一个卷):
- [root@docker-server ~]# docker run -it --name testnginx1 --volumes-from testnginx daocloud.io/library/nginx /bin/bash
- root@50e6f726335c:/# ls
- bin dev home lib64 mnt proc run srv test2 usr
- boot etc lib media opt root sbin sys tmp var
- root@50e6f726335c:/# cd test2/
- root@50e6f726335c:/test2# ls
- a.txt
复制代码
实际应用中可以利用多个-v选项把宿主机上的多个目录同时共享给新建容器:
比如:
- # docker run -it -v /abc:/abc -v /def:/def 镜像名称/ID
复制代码
6. Docker容器镜像打包
6.1 容器打包
将容器的文件系统打包成tar文件,也就是把正在运行的容器直接导出为tar包的镜像文件
注意: 这种方式,将tar包拷贝到其他机器运行容器的时候,必须加bash
有两种方式:
第一种:
- [root@docker-server ~]# docker images
- REPOSITORY TAG IMAGE ID CREATED SIZE
- centos 7 831691599b88 5 weeks ago 215MB
- [root@docker-server ~]# docker run -itd --name centos centos:7 /bin/bash
- [root@docker-server ~]# docker ps
- CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
- b028c756d20f centos "/bin/bash" About a minute ago Up About a minute centos
- [root@docker-server ~]# docker exec -it centos /bin/bash
- [root@96e2b7265d93 /]# vi a.txt #编辑一个文件
- 123
- [root@96e2b7265d93 /]# yum install -y vim wget #安装一个软件
- [root@docker-server ~]# docker export -o centos7-1.tar 96e2b726
- -o, --output
- [root@docker-server ~]# ls #保存到当前目录下
- anaconda-ks.cfg centos7-1.tar
复制代码
第二种:
- [root@docker-server ~]# docker export 容器名称 > 镜像.tar
复制代码
导入镜像文件迁移到其他宿主机:
import
- [root@docker-server ~]# docker import centos7-1.tar centos7-1:v1
- [root@docker-server ~]# docker images
- [root@docker-server ~]# docker run -it --name c6.1 centos7-1:v1 /bin/bash
- [root@4a29d58d3bd2 /]# ls
- a.txt bin dev etc home lib lib64 lost+found media mnt opt proc root sbin selinux srv sys tmp usr var
- [root@4a29d58d3bd2 /]# cat a.txt
- 123123
复制代码
6.2 将容器提交本地镜像
背景:容器运行起来后,又在里面做了一些操作,并且要把操作结果保存到镜像里
方案:使用 docker commit 指令,把一个正在运行的容器,直接提交为一个镜像。
例子:
在容器内部新建了一个文件
- [root@docker-server ~]# docker run -it --name c7 daocloud.io/library/centos:7 /bin/bash
- [root@2e8f79cb5922 /]# touch test.txt
复制代码
将这个新建的容器提交到镜像中保存
- [root@docker-server ~]# docker commit 2e8f79cb5922 soso/test:v2
- [root@docker-server ~]# docker images
复制代码
也可以这样例子:
- # docker commit -m "my images version1" -a "feige" 108a85b1ed99 soso/test:v2
复制代码- -m 添加注释
- -a 作者
- 108a85b1ed99 容器环境id
- soso/test:v2 镜像名称:hub的名称/镜像名称:tag
- -p,–pause=true 提交时暂停容器运行
复制代码
6.3 将本地镜像打包
保存一台宿主机上的镜像为tar文件,然后可以迁移到其他的宿主机上:
save
将镜像打包,与下面的load命令相对应
- [root@docker-server ~]# docker save -o nginx.tar daocloud.io/library/nginx:latest
复制代码
load
与上面的save命令相对应,将上面sava命令打包的镜像通过load命令导入,(实验环境中原来机器上面有镜像可以先删除掉。)
- [root@docker-server ~]# docker load < nginx.tar
- [root@docker-server ~]# docker images
复制代码- 把容器导出成tar包 export import
- 把容器做成镜像 commit -a "" -m ""
- 把镜像保存为tar包 save load
复制代码
7. 通过Dockerfile构建镜像
Docker 在镜像的设计中,引入了层(layer)的概念。也就是说,用户制作镜像的每一步操作,都会生成一个层,也就是一个增量rootfs。
第一部分:只读层。
它是这个容器的 rootfs 最下面的五层,对应的正是 ubuntu:latest 镜像的五层。可以看到,它们的挂载方式都是只读的(ro+wh,即 readonly+whiteout,至于什么是 whiteout?)。
第二部分:可读写层。
它是这个容器的 rootfs 最上面的一层,它的挂载方式为:rw,即 read write。在没有写入文件之前,这个目录是空的。而一旦在容器里做了写操作,你修改产生的内容就会以增量的方式出现在这个层中。
这个可读写层的作用,就是专门用来存放你修改 rootfs 后产生的增量,无论是增、删、改,都发生在这里。而当我们使用完了这个被修改过的容器之后,还可以使用 docker commit 和 push 指令,保存这个被修改过的可读写层,并上传到 Docker Hub 上,供其他人使用;而与此同时,原先的只读层里的内容则不会有任何变化。这,就是增量rootfs 的好处。
第三部分:Init 层。
它是一个以“-init”结尾的层,夹在只读层和读写层之间。Init 层是 Docker 项目单独生成的一个内部层,专门用来存放 /etc/hosts、/etc/resolv.conf 等信息。
需要这样一层的原因是,这些文件本来属于只读的 Ubuntu 镜像的一部分,但是用户往往需要在启动容器时写入一些指定的值比如 hostname,所以就需要在可读写层对它们进行修改。
可是,这些修改往往只对当前的容器有效,我们并不希望执行 docker commit 时,把这些信息连同可读写层一起提交掉。所以,Docker 做法是,在修改了这些文件之后,以一个单独的层挂载了出来。而用户执行 docker commit 只会提交可读写层,所以是不包含这些内容的。
Dockerfile 是一个用来构建镜像的文本文件,文本内容包含了一条条构建镜像所需的指令和操作命令;每一条指令构建一层镜像,因此每一条指令的内容,就是描述该层镜像应当如何构建(也就是你要执行的操作命令)。
7.1 Dockerfile指令集
- FROM 这个镜像的妈妈是谁?(指定基础镜像)
- MAINTAINER 告诉别人,谁负责养它?(指定维护者信息,可以没有)LABLE key=values
- RUN 你想让它干啥(在命令前面加上RUN即可)
- ADD/COPY 给它点创业资金(COPY文件,会自动解压)
- WORKDIR 我是cd,今天刚化了妆(设置当前工作目录)
- VOLUME 给它一个存放行李的地方(设置卷,挂载主机目录)
- EXPOSE 它要打开的门是啥(指定对外的端口)
- CMD 奔跑吧,兄弟!(指定容器启动后的要干的事情)
- ENTRYPOINT 容器启动命名
- ENV 环境变量
- USER 切换用户
复制代码
Docker 提供了一种更便捷的方式,叫作 Dockerfile
- docker build命令用于根据给定的Dockerfile构建Docker镜像
复制代码
docker build语法:
- # docker build [OPTIONS] <PATH | URL | ->
复制代码- 1. 常用选项说明
- --build-arg,设置构建时的变量
- --no-cache,默认false。设置该选项,将不使用Build Cache构建镜像
- --pull,默认false。设置该选项,总是尝试pull镜像的最新版本
- --compress,默认false。设置该选项,将使用gzip压缩构建的上下文
- --disable-content-trust,默认true。设置该选项,将对镜像进行验证
- --file, -f,Dockerfile的完整路径,默认值为‘PATH/Dockerfile’
- --isolation,默认--isolation="default",即Linux命名空间;其他还有process或hyperv
- --label,为生成的镜像设置metadata
- --squash,默认false。设置该选项,将新构建出的多个层压缩为一个新层,但是将无法在多个镜像之间共享新层;设置该选项,实际上是创建了新image,同时保留原有image。
- --tag, -t,镜像的名字及tag,通常name:tag或者name格式;可以在一次构建中为一个镜像设置多个tag
- --network,默认default。设置该选项,Set the networking mode for the RUN instructions during build
- --quiet, -q ,默认false。设置该选项,Suppress the build output and print image ID on success
- --force-rm,默认false。设置该选项,总是删除掉中间环节的容器
- --rm,默认--rm=true,即整个构建过程成功后删除中间环节的容器
复制代码- 示例:
- docker build -t soso/bbauto:v2.1 .
- docker build 是docker创建镜像的命令
- -t 是标识新建的镜像属于 soso的 bbauto镜像
- :v2.1 是tag
- "."是用来指明 我们的使用的Dockerfile文件当前目录的(也可以跟绝对路径)
复制代码
2.1、 创建镜像所在的文件夹和Dockerfile文件
- [root@docker-server ~]# mkdir sinatra
- [root@docker-server ~]# cd sinatra/
- [root@docker-server sinatra]# touch Dockerfile
复制代码
2.2、 在Dockerfile文件中写入指令,每一条指令都会更新镜像的信息例如:
- [root@docker-server sinatra]# vim Dockerfile
- #This is a comment
- FROM daocloud.io/library/centos:7 #基于哪个基础镜像
- MAINTAINER soso soso@docker-server #指定作者(可选)
- RUN touch a.txt
- RUN mkdir /test
- RUN yum -y install vim
复制代码
格式说明:
- 命令要大写,"#"是注解。
- 每一个指令后面需要跟空格,语法。:q
- FROM 命令是告诉docker 我们的镜像什么从哪里下载。
- MAINTAINER 是描述 镜像的创建人。
- RUN 命令是在镜像内部执行。就是说他后面的命令应该是针对镜像可以运行的命令。
复制代码
2.3、创建镜像
- 命令:
- # docker build -t soso/centos:7 .
- docker build 是docker创建镜像的命令
复制代码
详细执行过程:
- [root@docker-server sinatra]# docker build -t soso/centos:7 .
- Sending build context to Docker daemon 2.048kB
- Step 1/4 : FROM daocloud.io/library/centos
- latest: Pulling from library/centos
- d8d02d457314: Pull complete
- Digest: sha256:a36b9e68613d07eec4ef553da84d0012a5ca5ae4a830cf825bb68b929475c869
- Status: Downloaded newer image for daocloud.io/library/centos:latest
- ---> 67fa590cfc1c
- Step 2/4 : MAINTAINER soso soso@docker-server
- ---> Running in aab3d80939d8
- Removing intermediate container aab3d80939d8
- ---> 12bae7d75a23
- ....
复制代码
2.4、创建完成后,从镜像创建容器
7.2 单阶段构建镜像
- #下载基础镜像
- docker pull nginx
- #编写Dockerfile
- vim Dockerfile
- FROM nginx
- CMD ["nginx","-g","daemon off;"]
- #构建镜像
- docker build -t nginx:v1.1 .
- #运行容器
- docker run -itd --name nginx -p 80:80 nginx:v1.1
- #查看容器
- docker ps
复制代码
页面访问nginx即可
7.3 多阶段构建镜像
- #编写Dockerfile
- FROM nginx:v1.1 as builder
- FROM centos
- RUN mkdir /test
- COPY --from=builder /etc/nginx/nginx.conf /test
- #构建镜像
- docker build -t centos:v1.2 .
- #查看镜像
- docker images
- #起容器验证,centos中的文件是否拷贝过来
复制代码
7.4 Dockerfile(Jenkins)
- 做实验之前,必须得把宿主机的ipv4路由转发功能打开(如果遇到容器访问不到的情况)
- echo "net.ipv4.ip_forward=1" >> /etc/sysctl.conf
- sysctl -p
- 1.创建一个jenkins的Dockerfile
- [root@docker-server ~]# mkdir tomcat
- [root@docker-server ~]# cd tomcat/
- 将以下安装包拷贝至tomcat目录中
- [root@docker-server1 tomcat]# ls
- apache-tomcat-8.5.47.tar.gz Dockerfile jdk-8u211-linux-x64.tar.gz jenkins.war
- [root@docker-server tomcat]# vim Dockerfile
- # This my first jenkins Dockerfile
- # Version 1.0
- FROM centos:7
- MAINTAINER docker-server
- ENV JAVA_HOME /usr/local/jdk1.8.0_211
- ENV TOMCAT_HOME /usr/local/apache-tomcat-8.5.47
- ENV PATH=$JAVA_HOME/bin:$PATH
- ADD apache-tomcat-8.5.47.tar.gz /usr/local/
- ADD jdk-8u211-linux-x64.tar.gz /usr/local/
- RUN rm -rf /usr/local/apache-tomcat-8.5.47/webapps/*
- ADD jenkins.war /usr/local/apache-tomcat-8.5.47/webapps
- RUN rm -rf apache-tomcat-8.5.47.tar.gz jdk-8u211-linux-x64.tar.gz
- EXPOSE 8080
- ENTRYPOINT ["/usr/local/apache-tomcat-8.5.47/bin/catalina.sh","run"] #运行命令
- [root@docker-server tomcat]# pwd
- /root/tomcat
- [root@docker-server tomcat]# ls #将jdk与tomcat还有jenkins的包上传到tomcat目录中
- apache-tomcat-8.5.47.tar.gz Dockerfile jdk-8u211-linux-x64.tar.gz jenkins.war
- [root@docker-server tomcat]# docker build -t jenkins:v1 .
- [root@docker-server tomcat]# docker run -itd --name jenkins1 -p 8081:8080 jenkins:v1
复制代码
7.5 Dockerfile(Nginx)
- FROM centos:7
- RUN buildDeps='readline-devel pcre-devel openssl-devel gcc telnet wget curl make' \
- && useradd -M -s /sbin/nologin nginx \
- && mkdir -p /usr/local/nginx/conf/vhost \
- && mkdir -p /data/logs/nginx \
- && yum -y install $buildDeps \
- && yum clean all \
- && wget http://nginx.org/download/nginx-1.23.4.tar.gz \
- && tar zxf nginx-1.23.4.tar.gz \
- && cd nginx-1.23.4 \
- && ./configure --prefix=/usr/local/nginx \
- --with-http_ssl_module \
- --with-http_stub_status_module \
- && make -j 1 && make install \
- && rm -rf /usr/local/nginx/html/* \
- && echo "linux cloud 2301" >> /usr/local/nginx/html/cloud.html \
- && cd / && rm -rf nginx-1.23.4* \
- && ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
-
- ENV PATH /usr/local/nginx/sbin:$PATH
- COPY nginx.conf /usr/local/nginx/conf/nginx.conf
- WORKDIR /usr/local/nginx
- EXPOSE 80
- CMD ["nginx", "-g", "daemon off;"] #前台显示,长时间驻留
复制代码- # docker run -itd --name nginx1 -p 8082:80 nginx:1.23.4
复制代码
7.6 CMD与ENTRYPOINT区别
- 一、Dockerfile中的CMD
- CMD如果使用dockerfile时用的是CMD,那么启动容得时候就不需要加解释器了,如果加了解释器,那么CMD就失效了
- ENTRYPOINT如果使用dockerfile时用ENTRYPOINT,那么启动容器时加不加解释器就无所谓了,命令都会执行
- 1、每个Dockerfile中只能有一个CMD如果有多个那么只执行最后一个。
- 2、CMD 相当于启动docker时候后面添加的参数看,举个简单例子:
- # docker run -itd --name test image(镜像) /bin/bash -c
- a、镜像名称后面跟了一个/bin/bash -c ,其实等价于在dockerfile中的CMD ["/bin/bash","-c"]。
- b、如果dockerfile中的CMD中有了CMD["/bin/bash","-c"],那么就不用在执行的时候再添加了,如果添加了参数的话那么就相当于要执行你添加的参数,默认的CMD中的参数就无效了。
- 二、Dockerfile中的ENTRYPOINT
- 1、一个Dockerfile中ENTRYPOINT也只能存在一个,若存在多个那么只执行最后一个,你可以理解为开机启动的意思,和CMD有点像,不过还是有区别。
- 2、举个简单例子:
- a、Dockerfile中有ENTRYPOINT ["tail","-f","/var/log/nginx/access.log"],那么启动的时候镜像就执行了这个里面的内容,如果你像上面带参数的话就相当于在这个执行的内容后面再加入参数。
- 案例:
- 如果我们的dockerfile中有a中的这句话然后我们启动我们的docker:
- # docker run -itd --name test image(镜像名) /bin/bash -c
- 此时就相当于我们启动docker的时候执行了:tail -f /var/log/nginx/access.log /bin/bash -c
- 这个命令明显就不对.
复制代码
参考链接:https://blog.csdn.net/k_520_w/article/details/111731198
7.7 Dockerfile优化
- 1、多阶段构建镜像
- 使用多个FROM指令,将构建过程分为多个阶段;每个阶段生成一个独立的镜像,后续阶段可以使用前面阶段生成的镜像作为基础镜像。多阶段构建可以有效减小最终镜像的体积,分离构建环境和运行环境多阶段构建。它允许在一个Dockerfile中使用多个FROM指令,每个FROM指令都可以使用不同的基础镜像,并且每个FROM指令都开始一个新的构建阶段。多阶段构建的主要目的是**将构建过程分为多个独立的阶段**,**每个阶段生成一个独立的镜像**。后续阶段可以使用前面阶段生成的镜像作为基础镜像,从而实现构建环境和运行环境的分离,有效减小最终镜像的体积。
- 2、把不需要的命令输出丢入/dev/null
- 对于某些命令的标准输出和错误输出,如果不需要,可以重定向到/dev/null,避免不必要的输出写入镜像层,减小镜像体积。使用command > /dev/null 2>&1的形式进行重定向
- 3、使用普通用户运行
- 在Dockerfile中使用USER指令切换到非root用户,以最小权限原则运行应用,提高安全性。确保应用程序有足够权限访问所需资源
- 4、选择合适的基础镜像
- Alpine Linux是一个面向安全的轻型Linux发行版,镜像体积小,相比Ubuntu、CentOS等,Alpine Linux更适合作为基础镜像,务必评估Alpine Linux与应用程序的兼容性。
- 5、减少镜像层数
- 1、RUN 命令要尽量写在一条里,每次 RUN 命令都是在之前的镜像上封装,只会增大不会减小
- 6、每次进行依赖安装后,记得yum clean all
复制代码
8. 部署私有仓库应用
私有仓库镜像:
registry --官方出品, 没有图形界面。Docker hub官方已提供容器镜像registry,用于搭建私有仓库
拉取镜像:
- [root@docker-server ~]# docker pull daocloud.io/library/registry:latest
复制代码
运行容器:
- [root@docker-server ~]# docker run -itd -v /home/dockerdata/registry:/var/lib/registry --name "pri_registry" --restart=always -p 5000:5000 daocloud.io/library/registry:latest
- 参数解释:
- /home/dockerdata/registry表示为宿主机的目录,如果不存在自动创建
- -v映射目录: 宿主机的目录:容器目录
- 把宿主机的目录挂载到容器中,将数据目录挂载出来就是为了防止docker私有仓库这个容器被删除的时候,仓库里面的镜像也被删除。
- -p 端口映射:本地端口:容器端口
复制代码
注:如果创建容器不成功,报错防火墙,解决方案如下
- # systemctl stop firewalld
- # yum install iptables*
- # systemctl start iptables
- # iptables -F
- # systemctl restart docker
复制代码- [root@docker-server ~]# docker ps
复制代码
连接容器查看端口状态:
- [root@docker-server ~]# docker exec -it 0823df7 /bin/sh
- / # netstat -lntp #查看5000端口是否开启
- Active Internet connections (only servers)
- Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
- tcp 0 0 :::5000 :::* LISTEN 1/registry
复制代码
在本机查看能否访问该私有仓库, 看看状态码是不是200
- [root@docker-server ~]# curl -I http://127.0.0.1:5000
复制代码
为了测试,下载1个比较小的镜像,busybox
- [root@docker-server ~]# docker pull daocloud.io/library/busybox
复制代码
上传前必须给镜像打tag 注明ip和端口:
- [root@docker-server ~]# docker tag daocloud.io/library/busybox 192.168.246.141:5000/busybox
复制代码
下面这个Mysql是我测试的第二个镜像,从daocloud拉取的:
- [root@docker-server ~]# docker pull daocloud.io/library/mysql
- [root@docker-server ~]# docker tag daocloud.io/library/mysql 192.168.246.141:5000/daocloud.io/library/mysql
- [root@docker-server ~]# docker images
复制代码
注:tag后面可以使用镜像名称也可以使用id,我这里使用的镜像名称,如果使用官方的镜像,不需要加前缀,但是daocloud.io的得加前缀.
- [root@docker-server ~]# docker push 10.8.166.252:5000/busybox:latest
- 现在推送,会报下面错误:
复制代码
修改请求方式为http:
- 默认为https,不改会报以下错误:
- Get https://master.up.com:5000/v1/_ping: http: server gave HTTP response to HTTPS client
- [root@docker-server ~]# vim /etc/docker/daemon.json #不存在则创建
- { "insecure-registries":["192.168.246.141:5000"] }
复制代码
注释:第一行是Docker镜像加速器。后面一定要跟逗号;第二行是仓库地址
- 重启docker:
- [root@docker-server ~]# systemctl restart docker
复制代码
上传镜像到私有仓库:
- [root@docker-server ~]# docker push 192.168.246.141:5000/busybox
- [root@docker-server ~]# docker push 192.168.246.141:5000/daocloud.io/library/mysql
- 宿主机查看存放镜像目录:
- [root@docker-server ~]# ls /home/dockerdata/registry/docker/registry/v2/repositories/
复制代码
查看私有仓库里的所有镜像:
- 这条命令会查看仓库下面所有的镜像:
- [root@docker-server ~]# curl http://192.168.246.141:5000/v2/_catalog
- 语法: # curl http://ip:port/v2/repo名字/tags/list
- [root@docker-server ~]# curl http://192.168.246.141:5000/v2/busybox/tags/list
- {"name":"busybox","tags":["latest"]}
- [root@docker-server ~]# curl http://192.168.246.141:5000/v2/daocloud.io/li brary/mysql/tags/list
- {"name":"daocloud.io/library/mysql","tags":["latest"]}
复制代码
拉取镜像测试:
- 1.先将刚才打了tags的镜像删掉
- [root@docker-server ~]# docker rmi 192.168.246.141:5000/busybox
- 2.拉取镜像:
- [root@docker-server ~]# docker pull 192.168.246.141:5000/busybox
- [root@docker-server ~]# docker images
复制代码
9. docker页面管理工具
下载并运行容器:
- [root@docker-server ~]# docker pull uifd/ui-for-docker
- [root@docker-server ~]# docker run -it -d --name docker-web -p 9000:9000 -v /var/run/docker.sock:/var/run/docker.sock docker.io/uifd/ui-for-docker
复制代码
浏览器访问测试:
ip:9000
10. systemctl启动服务
镜像下载:
- [root@docker-server ~]# docker pull daocloud.io/library/centos:7
复制代码
systemd 整合:
- 因为 systemd 要求 CAPSYSADMIN 权限,从而得到了读取到宿主机 cgroup 的能力,CentOS7 中已经用 fakesystemd 代替了 systemd 。 但是我们使用systemd,可用参考下面的 Dockerfile:
复制代码- [root@docker-server ~]# mkdir test
- [root@docker-server ~]# cd test/
- [root@docker-server test]# vim Dockerfile
- FROM daocloud.io/library/centos:7
- MAINTAINER "soso" soso@qq.com
- ENV container docker
- RUN yum -y swap -- remove fakesystemd -- install systemd systemd-libs
- RUN yum -y update; yum clean all; \
- (cd /lib/systemd/system/sysinit.target.wants/; for i in *; do [ $i == systemd-tmpfiles-setup.service ] || rm -f $i; done); \
- rm -f /lib/systemd/system/multi-user.target.wants/*;\
- rm -f /etc/systemd/system/*.wants/*;\
- rm -f /lib/systemd/system/local-fs.target.wants/*; \
- rm -f /lib/systemd/system/sockets.target.wants/*udev*; \
- rm -f /lib/systemd/system/sockets.target.wants/*initctl*; \
- rm -f /lib/systemd/system/basic.target.wants/*;\
- rm -f /lib/systemd/system/anaconda.target.wants/*;
- VOLUME [ "/sys/fs/cgroup" ] #指定逻辑卷
- CMD ["/usr/sbin/init"] #代表的是把上面的服务拉起来
复制代码
这个Dockerfile删除fakesystemd 并安装了 systemd。然后再构建基础镜像:
- [root@docker-server test]# docker build -t local/c7-systemd .
复制代码
执行没有问题这就生成一个包含 systemd 的应用容器示例
- [root@docker-server test]# docker images
- REPOSITORY TAG IMAGE ID CREATED SIZE
- local/c7-systemd latest a153dcaa642e 6 minutes ago 391MB
复制代码
为了使用像上面那样包含 systemd 的容器,需要创建一个类似下面的Dockerfile:
- [root@docker-server test]# mkdir http
- [root@docker-server test]# cd http/
- [root@docker-server http]# vim Dockerfile
- FROM local/c7-systemd
- RUN yum -y install httpd; yum clean all; systemctl enable httpd.service
- EXPOSE 80
- CMD ["/usr/sbin/init"]
- 或者
- [root@docker-server http]# cat Dockerfile
- FROM local/c7-systemd
- RUN rm -rf /etc/yum.repos.d/*
- ADD Centos-7.repo /etc/yum.repos.d/
- RUN yum -y install httpd; yum clean all; systemctl enable httpd
- EXPOSE 80
- CMD ["/usr/sbin/init"]
复制代码
构建镜像:
- [root@docker-server http]# docker build -t local/c7-systemd-httpd .
复制代码
运行包含 systemd 的应用容器:
为了运行一个包含 systemd 的容器,需要使用–privileged选项, 并且挂载主机的 cgroups 文件夹。 下面是运行包含 systemd 的 httpd 容器的示例命令:
- [root@docker-server http]# docker run --privileged -tid -v /sys/fs/cgroup:/sys/fs/cgroup:ro -p 80:80 local/c7-systemd-httpd
- --privileged:授权提权。让容器内的root用户拥有真正root权限(有些权限是没有的)
- ro代表的是只读
- rw代表的是读写
复制代码
注意:如果不加会运行在前台(没有用-d),可以用ctrl+p+q放到后台去
测试可用:
- [root@docker-server http]# yum install -y elinks
- [root@docker-server http]# elinks --dump http://192.168.246.141 #apache的默认页面
- Testing 123..
- This page is used to test the proper operation of the [1]Apache HTTP
- server after it has been installed. If you can read this page it means
- that this site is working properly. This server is powered by [2]CentOS.
复制代码
再来个安装openssh-server的例子:
- [root@docker-server http]# cd ..
- [root@docker-server test]# mkdir ssh
- [root@docker-server test]# cd ssh/
- [root@docker-server ssh]# vim Dockerfile
- FROM local/c7-systemd
- RUN yum -y install openssh-server; yum clean all; systemctl enable sshd.service
- RUN echo 123456 | passwd --stdin root
- EXPOSE 22
- CMD ["/usr/sbin/init"]
- [root@docker-server ssh]# docker build -t local/c7-systemd-sshd .
- [root@docker-server ssh]# docker run --privileged -tid -v /sys/fs/cgroup:/sys/fs/cgroup:ro -p 2222:22 local/c7-systemd-sshd
- [root@docker-server ssh]# ssh 192.168.246.141 -p 2222
- [root@ce1af52a6f6c ~]#
复制代码
11. 修改Docker数据存储位置
- 查看存储路径:
- [root@docker-server ~]# docker info | grep Root
- Docker Root Dir: /var/lib/docker
- 修改默认存储位置:
- 在ExecStart的启动命令后面追加--data-root参数指定新的位置
- [root@docker-server ~]# vim /usr/lib/systemd/system/docker.service
- ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock --data-root=/data
- [root@docker-server ~]# systemctl daemon-reload
- [root@docker-server ~]# systemctl restart docker
- 查看是否生效:
- [root@docker-server ~]# docker info | grep Root
- Docker Root Dir: /data
-
- [root@docker-server ~]# cd /data/
- [root@docker-server data]# ls
- builder buildkit containers image network overlay2 plugins runtimes swarm tmp trust volumes
复制代码
12. Docker网络
Docker网络分类
Docker默认使用桥接模式,在宿主机虚拟一个Docker容器网桥(docker0),Docker启动一个容器时会根据Docker网桥的网段分配给容器一个IP地址,称为Container-IP,同时Docker网桥是每个容器的默认网关。因为在同一宿主机内的容器都接入同一个网桥,这样容器之间就能够通过容器的 Container-IP 直接通信。
Docker网桥是宿主机虚拟出来的,并不是真实存在的网络设备,外部网络是无法寻址到的,这也意味着外部网络无法直接通过 Container-IP 访问到容器。如果容器希望外部访问能够访问到,可以通过映射容器端口到宿主主机(端口映射),即docker run创建容器时候通过-p参数来启用,访问容器的时候就通过[宿主机IP]:[端口]访问容器。
注:
面试用,用了编排之后就没有用了
查看当前网络:
- [root@docker-server ~]# docker network list
- NETWORK ID NAME DRIVER SCOPE
- 9b902ee3eafb bridge bridge local
- 140a9ff4bb94 host host local
- d1210426b3b0 none null local
复制代码
docker安装后,默认会创建4种网络类型,bridge、host和none container网络
1、bridge:网络桥接
- Docker默认的容器网络驱动。此模式会为每一个容器分配、设置IP等,并将容器连接到一个docker0虚拟网桥,通过docker0网桥以及iptables nat 表配置与宿主机通信。
复制代码
2、none:无指定网络
3、host:主机网络
- 容器与主机共享同一Network Namespace,共享同一套网络协议栈、路由表及iptables规则等。容器与主机看到的是相同的网络视图。(docker容器和主机共用一个ip地址)
- 使用host网络创建容器:
- [root@docker-server ~]# docker run -it --name testnginx2 --net host 98ebf73ab
- [root@docker-server ~]# netstat -lntp | grep 80
- tcp6 0 0 :::80 :::* LISTEN 3237/docker-proxy
- 浏览器访问宿主ip地址
复制代码
4、container模式
- 创建的容器不会创建自己的网卡,配置自己的IP,而是和一个指定的容器共享IP、端口
- docker run -itd --name ssh2 --net=container:ssh local/c7-systemd-sshd /bin/bash
- docker exec -it ssh2 bash
- yum -y install epel-release
- yum -y install nginx
- 启动nginx:nginx
- 用telnet访问ssh容器的加端口,进行测试
- --net=container:容器名或者id(要共享的容器)
复制代码
固定ip:
创建固定ip的容器:
- 4.1、创建自定义网络类型,并且指定网段
- [root@docker-server ~]# docker network create --subnet=192.168.0.0/16 staticnet
- 通过docker network ls可以查看到网络类型中多了一个staticnet:
- [root@docker-server ~]# docker network ls
- NETWORK ID NAME DRIVER SCOPE
- 9b902ee3eafb bridge bridge local
- 140a9ff4bb94 host host local
- d1210426b3b0 none null local
- 4efd309244c6 staticnet bridge local
复制代码- 4.2、使用新的网络类型创建并启动容器
- [root@docker-server ~]# docker run -itd --name server --net staticnet --ip 192.168.0.2 daocloud.io/library/centos:7
- 通过docker inspect可以查看容器ip为192.168.0.2:
- [root@docker-server ~]# docker inspect server | grep -i ipaddress
- "SecondaryIPAddresses": null,
- "IPAddress": "",
- "IPAddress": "192.168.0.2",
- 关闭容器并重启,发现容器ip并未发生改变
复制代码- 4.3、删除已创建网络
- 需要删除使用当前网络的容器。才能删除网络
- [root@docker-server]# docker network rm staticnet
复制代码