前言:Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的 Linux 机器上,也可以实现虚拟化。容器是完全使用沙箱机制,相互之间不会有任何接口。
一、概述
1.Docker概念
1)Docker是什么
- 是一种轻量级的“虚拟机”
- 在Linux容器里运行应用的开源工具
- Docker的设计宗旨:Build、Ship and Run Any App、Anywhere,即通过对应用组件的封装、发布、部署、运行等生命周期的管理,达到应用组件级别的“一次封装,到处运行”的目的。这里的组件,既可以是一个应用,也可以是一套服务,甚至是一个完整的操作系统
2)Docker与虚拟机的区别
3)Docker的使用场景
- 打包应用程序简化部署
- 可脱离底层硬件任意迁移
- 例如:服务器从腾讯云迁移到阿里云
2.Docker的核心概念及安装方式
1)Docker核心概念
1.1 镜像(Image)
- Docker的镜像是创建容器的基础,类似虚拟机的快照,可以理解为是一个面向Docker容器引擎的只读模板,比如:一个镜像可以是一个完整的CentOS操作系统环境,称为一个CentOS镜像;可以是一个安装了MySQL的应用程序,称之为一个MySQL镜像等等
1.2 容器(Container)
- Docker的容器时从镜像创建的运行实例,它可以被启动、停止和删除。所创建的每一个容器都是相互隔离、互不可见的,可以保证平台的安全性。还可以把容器看作是一个简易版的Linux环境,Docker利用容器来运行和隔离应用
1.3 仓库(Repository)
- Docker仓库是用来集中保存镜像的地方,当创建了自己的镜像之后,可以使用push命令将它上传到公共仓库(public)或者私有仓库(private),这样一来当下次要在另一台机器上使用这个镜像的时候,只需要从仓库上pull下来就可以了
- 仓库注册服务器(registry)是存放放库的地方,其中包含了多个仓库,每个仓库集中存放某一类镜像,并且使用不同的标签(tag)来区分它们。目前最大的公共仓库是Docker Hub,其中存放了数量庞大的镜像供用户下载使用
- 一个完整的Docker有以下几个部分组成:
- Docker Client客户端
- Docker Daemon守护进程
- Docker Image镜像
- Docker Container容器
2)centos安装docker的两种方式
- 使用CURL获得Docker的安装脚本进行安装
- 使用YUM仓库来安装Docker
3.Docker架构
- Docker 使用客户端-服务器 (C/S) 架构模式,使用远程API来管理和创建Docker容器。Docker 容器通过 Docker 镜像来创建。容器与镜像的关系类似于面向对象编程中的对象与类。
-
Docker采用 C/S架构 Docker daemon 作为服务端接受来自客户的请求,并处理这些请求(创建、运行、分发容器)。 客户端和服务端既可以运行在一个机器上,也可通过 socket 或者RESTful API 来进行通信。
-
Docker daemon 一般在宿主主机后台运行,等待接收来自客户端的消息。 Docker 客户端则为用户提供一系列可执行命令,用户用这些命令实现跟 Docker daemon 交互。
特性
- 在docker的网站上提到了docker的典型场景:
- Automating the packaging and deployment of applications(使应用的打包与部署自动化)
- Creation of lightweight, private PAAS environments(创建轻量、私密的PAAS环境)
- Automated testing and continuous integration/deployment(实现自动化测试和持续的集成/部署)
- Deploying and scaling web apps, databases and backend services(部署与扩展webapp、数据库和后台服务)
- 由于其基于LXC的轻量级虚拟化的特点,docker相比KVM之类最明显的特点就是启动快,资源占用小。因此对于构建隔离的标准化的运行环境,轻量级的PaaS(如dokku), 构建自动化测试和持续集成环境,以及一切可以横向扩展的应用(尤其是需要快速启停来应对峰谷的web应用)。
- 构建标准化的运行环境,现有的方案大多是在一个baseOS上运行一套puppet/chef,或者一个image文件,其缺点是前者需要base OS许多前提条件,后者几乎不可以修改(因为copy on write 的文件格式在运行时rootfs是read only的)。并且后者文件体积大,环境管理和版本控制本身也是一个问题
- PaaS环境是不言而喻的,其设计之初和dotcloud的案例都是将其作为PaaS产品的环境基础
- 因为其标准化构建方法(buildfile)和良好的REST API,自动化测试和持续集成/部署能够很好的集成进来
- 因为LXC轻量级的特点,其启动快,而且docker能够只加载每个container变化的部分,这样资源占用小,能够在单机环境下与KVM之类的虚拟化方案相比能够更加快速和占用更少资源
局限
- Docker并不是全能的,设计之初也不是KVM之类虚拟化手段的替代品,简单总结几点:
- Docker是基于Linux 64bit的,无法在32bit的linux/Windows/unix环境下使用
- LXC是基于cgroup等linux kernel功能的,因此container的guest系统只能是linux base的
- 隔离性相比KVM之类的虚拟化方案还是有些欠缺,所有container公用一部分的运行库
- 网络管理相对简单,主要是基于namespace隔离
- cgroup的cpu和cpuset提供的cpu功能相比KVM的等虚拟化方案相比难以度量(所以dotcloud主要是按内存收费)
- Docker对disk的管理比较有限
- container随着用户进程的停止而销毁,container中的log等用户数据不便收集
原理
-
Docker核心解决的问题是利用LXC来实现类似VM的功能,从而利用更加节省的硬件资源提供给用户更多的计算资源。同VM的方式不同, LXC 其并不是一套硬件虚拟化方法 - 无法归属到全虚拟化、部分虚拟化和半虚拟化中的任意一个,而是一个操作系统级虚拟化方法, 理解起来可能并不像VM那样直观。所以我们从虚拟化到docker要解决的问题出发,看看他是怎么满足用户虚拟化需求的
-
用户需要考虑虚拟化方法,尤其是硬件虚拟化方法,需要借助其解决的主要是以下4个问题:
- 隔离性 - 每个用户实例之间相互隔离, 互不影响。 硬件虚拟化方法给出的方法是VM, LXC给出的方法是container,更细一点是kernel namespace
- 可配额/可度量 - 每个用户实例可以按需提供其计算资源,所使用的资源可以被计量。硬件虚拟化方法因为虚拟了CPU, memory可以方便实现, LXC则主要是利用cgroups来控制资源
- 移动性 - 用户的实例可以很方便地复制、移动和重建。硬件虚拟化方法提供snapshot和image来实现,docker(主要)利用AUFS实现
- 安全性 - 这个话题比较大,这里强调是host主机的角度尽量保护container。硬件虚拟化的方法因为虚拟化的水平比较高,用户进程都是在KVM等虚拟机容器中翻译运行的, 然而对于LXC, 用户的进程是lxc-start进程的子进程, 只是在Kernel的namespace中隔离的, 因此需要一些kernel的patch来保证用户的运行环境不会受到来自host主机的恶意入侵, dotcloud(主要是)利用kernel grsec patch解决的
二、部署
1.环境部署
- 关闭防火墙,增强性安全功能
[root@localhost ~]# vi /etc/selinux/config
[root@localhost ~]# systemctl stop firewalld.service
[root@localhost ~]# setenforce 0
- 安装依赖包
[root@localhost ~]# yum -y install yum-utils device-mapper-persistent-data lvm2
//设置阿里云镜像源
[root@localhost ~]# yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
Loaded plugins: fastestmirror, langpacks
adding repo from: https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
grabbing file https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo to /etc/yum.repos.d/docker-ce.repo
repo saved to /etc/yum.repos.d/docker-ce.repo
[root@localhost ~]# yum -y install -y docker-ce //安装Docker-CE
- 启动docker
[root@localhost ~]# systemctl start docker
[root@localhost ~]# systemctl enable docker
Created symlink from /etc/systemd/system/multi-user.target.wants/docker.service to /usr/lib/systemd/system/docker.service.
2.镜像加速操作
1)加速器地址创建
- 镜像加速需要自己去创建,首先注册一个阿里云账号,接着进入控制台选择容器镜像服务
- 创建好后,选择镜像加速器即可看到自己的加速器地址
2)配置镜像加速
- 进入守护进程配置文件,将加速器网址添加进去
[root@localhost ~]# tee /etc/docker/daemon.json <<-'EOF'
> {
> "registry-mirrors":["https://********.mirror.aliyuncs.com"]
> }
> EOF
{
"registry-mirrors":["https://********.mirror.aliyuncs.com"]
}
[root@localhost ~]# systemctl daemon-reload //重新加载守护进程
[root@localhost ~]# systemctl restart docker //重启docker服务
3.网络优化
[root@localhost ~]# vi /etc/sysctl.conf //设置路由转发
net.ipv4.ip_forward=1
[root@localhost ~]# sysctl -p //开启
net.ipv4.ip_forward = 1
[root@localhost ~]# service network restart
Restarting network (via systemctl): [ 确定 ]
[root@localhost ~]# systemctl restart docker
三、基本操作
查看版本
[root@localhost ~]# docker version 查看版本
Client: Docker Engine - Community
Version: 19.03.8
API version: 1.40
Go version: go1.12.17
Git commit: afacb8b
Built: Wed Mar 11 01:27:04 2020
OS/Arch: linux/amd64
Experimental: false
Server: Docker Engine - Community
Engine:
Version: 19.03.8
API version: 1.40 (minimum version 1.12)
Go version: go1.12.17
Git commit: afacb8b
Built: Wed Mar 11 01:25:42 2020
OS/Arch: linux/amd64
Experimental: false
containerd:
Version: 1.2.13
GitCommit: 7ad184331fa3e55e52b890ea95e65ba581ae3429
runc:
Version: 1.0.0-rc10
GitCommit: dc9208a3303feef5b3839f4323d9beb36df0a9dd
docker-init:
Version: 0.18.0
GitCommit: fec3683
1. 镜像操作
搜索镜像
[root@localhost docker]# docker search nginx
NAME DESCRIPTION STARS OFFICIAL AUTOMATED
nginx Official build of Nginx. 12948 [OK]
jwilder/nginx-proxy Automated Nginx reverse proxy for docker con… 1768 [OK]
richarvey/nginx-php-fpm Container running Nginx + PHP-FPM capable of… 764 [OK]
linuxserver/nginx An Nginx container, brought to you by LinuxS… 102
bitnami/nginx Bitnami nginx Docker Image 82 [OK]
tiangolo/nginx-rtmp Docker image with Nginx using the nginx-rtmp… 67
。。省略部分内容
- 其中返回的信息包括:镜像名称(NAME)、描述(DESCRIPTION)、星级(STARS)、是否官方创建(OFFICIAL)、是否主动创建(AUTOMATED)
下载镜像
[root@localhost docker]# docker pull nginx
Using default tag: latest
latest: Pulling from library/nginx
c499e6d256d6: Already exists
22c4cdf4ea75: Pull complete
6ff5091a5a30: Pull complete
2fd3d1af9403: Pull complete
0d9d26127d1d: Pull complete
54a67d4e7579: Pull complete
fe989230d866: Pull complete
3a808704d40c: Pull complete
826517d07519: Pull complete
69cd125db928: Pull complete
b5c43b8c2879: Pull complete
1811572b5ea5: Pull complete
Digest: sha256:b69d0b62d02ee1eba8c7aeb32eba1bb678b6cfa4ccfb211a5d7931c7755dc4a8
Status: Downloaded newer image for nginx:latest
docker.io/library/nginx:latest
- 从整个下载的过程可以看出,镜像文件由若干层(Layer)组成,我们称之为AUFS(联合文件系统),是实现增量保存与更新的基础,下载过程中会输出镜像的各层信息
查看下载镜像
[root@localhost docker]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
nginx latest ed21b7a8aee9 8 days ago 127MB
- 从回显的信息中可以读出以下信息:
- REPOSITORY——镜像属于的仓库
- TAG——镜像的标签信息,标记同一个仓库中的不同镜像
- IMAGE ID——镜像的唯一ID号,唯一标识了该镜像
- CREATED——镜像创建时间
- VIRTUAL SIZE——镜像大小
查看镜像详细信息
- 需要镜像的ID
[root@localhost docker]# docker inspect ed21b7a8aee9
[
{
"Id": "sha256:ed21b7a8aee9cc677df6d7f38a641fa0e3c05f65592c592c9f28c42b3dd89291",
"RepoTags": [
"nginx:latest"
],
"RepoDigests": [
"nginx@sha256:282530fcb7cd19f3848c7b611043f82ae4be3781cb00105a1d593d7e6286b596"
],
"Parent": "",
"Comment": "",
"Created": "2020-03-31T03:19:30.487069362Z",
"Container": "5c86b143cf5caec0aed5c331922c243f00600152ec0e9ecbe8531771562e72b8",
"ContainerConfig": {
"Hostname": "5c86b143cf5c",
"Domainname": "",
"User": "",
"AttachStdin": false,
"AttachStdout": false,
"AttachStderr": false,
"ExposedPorts": {
"80/tcp": {}
},
"Tty": false,
"OpenStdin": false,
"StdinOnce": false,
"Env": [
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
"NGINX_VERSION=1.17.9",
"NJS_VERSION=0.3.9",
"PKG_RELEASE=1~buster"
],
"Cmd": [
"/bin/sh",
"-c",
"#(nop) ",
"CMD [\"nginx\" \"-g\" \"daemon off;\"]"
],
"ArgsEscaped": true,
"Image": "sha256:9be1fc3b00d81a66f4de11f5f5bf176e0748434be056cf3152386cc917307e7f",
"Volumes": null,
"WorkingDir": "",
"Entrypoint": null,
"OnBuild": null,
"Labels": {
"maintainer": "NGINX Docker Maintainers <docker-maint@nginx.com>"
},
"StopSignal": "SIGTERM"
},
"DockerVersion": "18.09.7",
"Author": "",
"Config": {
"Hostname": "",
"Domainname": "",
"User": "",
"AttachStdin": false,
"AttachStdout": false,
"AttachStderr": false,
"ExposedPorts": {
"80/tcp": {}
},
"Tty": false,
"OpenStdin": false,
"StdinOnce": false,
"Env": [
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
"NGINX_VERSION=1.17.9",
"NJS_VERSION=0.3.9",
"PKG_RELEASE=1~buster"
],
"Cmd": [
"nginx",
"-g",
"daemon off;"
],
"ArgsEscaped": true,
"Image": "sha256:9be1fc3b00d81a66f4de11f5f5bf176e0748434be056cf3152386cc917307e7f",
"Volumes": null,
"WorkingDir": "",
"Entrypoint": null,
"OnBuild": null,
"Labels": {
"maintainer": "NGINX Docker Maintainers <docker-maint@nginx.com>"
},
"StopSignal": "SIGTERM"
},
"Architecture": "amd64",
"Os": "linux",
"Size": 126769107,
"VirtualSize": 126769107,
"GraphDriver": {
"Data": {
"LowerDir": "/var/lib/docker/overlay2/11d4943de374062831bf46e10c5756c95b53d0c95adde0b3098a95ef08e99c7f/diff:/var/lib/docker/overlay2/26fd25bb0e8af251d50da334dcf0c6eca2df114b55ad8fccdd97dd70297c3835/diff",
"MergedDir": "/var/lib/docker/overlay2/ccefd23166f163f28215b7c84f86e5562ded2bae14230105f56e63c07ccfde58/merged",
"UpperDir": "/var/lib/docker/overlay2/ccefd23166f163f28215b7c84f86e5562ded2bae14230105f56e63c07ccfde58/diff",
"WorkDir": "/var/lib/docker/overlay2/ccefd23166f163f28215b7c84f86e5562ded2bae14230105f56e63c07ccfde58/work"
},
"Name": "overlay2"
},
"RootFS": {
"Type": "layers",
"Layers": [
"sha256:c3a984abe8a88059915bb6c7a1d249fd1ccc16d931334ac8816540b0eb686b45",
"sha256:99134ec7f247e5a211c7205fec587bf72a6d4aac339b21858b892e9c04f78920",
"sha256:d37eecb5b7691ec21bd19989e37f8bb4d20b340a775591d0f3db5897d606b0e4"
]
},
"Metadata": {
"LastTagTime": "0001-01-01T00:00:00Z"
}
}
]
标记本地镜像,将其归入某一仓库
[root@localhost docker]# docker tag nginx:latest nginx:web //更改标签,相当于软连接
[root@localhost docker]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
nginx latest ed21b7a8aee9 9 days ago 127MB
nginx web ed21b7a8aee9 9 days ago 127MB
删除镜像
[root@localhost docker]# docker rmi nginx:web
Untagged: nginx:web
[root@localhost docker]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
nginx latest ed21b7a8aee9 9 days ago 127MB
保存镜像到当前目录
[root@localhost opt]# docker save -o nginx nginx:latest
[root@localhost opt]# ls
nginx rh
导入镜像
[root@localhost opt]# docker load < nginx
99134ec7f247: Loading layer [==================================================>] 58.11MB/58.11MB
d37eecb5b769: Loading layer [==================================================>] 3.584kB/3.584kB
Loaded image: nginx:latest
登录与上传
- 需要申请账号密码
docker login #登录
docker push nginx:web #上传
2.容器操作
创建容器
[root@localhost docker]# docker create -it nginx:latest /bin/bash //创建容器
eada03f2e287892b321248168c7a21aa44a067ed3cfd70a91629774bf753e8ef
查看容器
[root@localhost docker]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
eada03f2e287 nginx:latest "/bin/bash" 27 seconds ago Created stoic_cannon
启动、停止与删除容器
- 需要容器ID
[root@localhost docker]# docker start eada03f2e287 //启动
eada03f2e287
[root@localhost docker]# docker ps -a //查看状态为up
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
eada03f2e287 nginx:latest "/bin/bash" About a minute ago Up 18 seconds 80/tcp stoic_cannon
[root@localhost docker]# docker stop eada03f2e287 //停止
eada03f2e287
[root@localhost docker]# docker ps -a //查看状态为exited0 正常退出
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
eada03f2e287 nginx:latest "/bin/bash" About a minute ago Exited (0) 1 second ago stoic_cannon
[root@localhost docker]# docker rm eada03f2e287 //删除
eada03f2e287
[root@localhost docker]# docker ps -a //查看状态已删除
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
docker run
[root@localhost opt]# docker run mysql /bin/bash -c ls / //docker run 等同于创建,开启并查看后关闭容器,没有镜像会自动下载镜像
Unable to find image 'mysql:latest' locally
latest: Pulling from library/mysql
123275d6e508: Already exists
27cddf5c7140: Pull complete
c17d442e14c9: Pull complete
2eb72ffed068: Pull complete
d4aa125eb616: Pull complete
52560afb169c: Pull complete
68190f37a1d2: Pull complete
2dc788993ca1: Pull complete
a69f7038d031: Pull complete
354e8f265571: Pull complete
d886b3278ec0: Pull complete
4bafb67941a2: Pull complete
Digest: sha256:fc77c7d56aa74239e659d0bb4aa3268f476c595521f932e90aca530687709598
Status: Downloaded newer image for mysql:latest
bin
boot
dev
docker-entrypoint-initdb.d
entrypoint.sh
etc
home
lib
lib64
media
mnt
opt
proc
root
run
sbin
srv
sys
tmp
usr
var
[root@localhost opt]# docker ps -a //查看完后容器显示关闭
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
d10ec6838345 mysql "docker-entrypoint.s…" 2 minutes ago Exited (0) 2 minutes ago
进入容器
[root@localhost opt]# docker create -it paigeeworld/centos7 /bin/bash //创建一个容器
36f89796362c4797fcdc568bfde848a5604f1e7bd0bb88ef4a94548682afdaae
[root@localhost opt]# docker ps -a //查看
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
36f89796362c paigeeworld/centos7 "/bin/bash" 54 seconds ago Created romantic_maxwell
[root@localhost opt]# docker start 36f89796362c //开启容器
36f89796362c
[root@localhost opt]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
36f89796362c paigeeworld/centos7 "/bin/bash" About a minute ago Up 1 second romantic_maxwell
[root@localhost opt]# docker exec -it 36f89796362c /bin/bash //进入容器
bash-4.2#
bash-4.2# exit //exit退出
exit
- 使容器持续运行
[root@localhost opt]# docker run -d paigeeworld/centos7 /bin/bash -c "while true;do echo hello;done" //持续在后台执行 -d守护进程 -c指向
c0cb5c27515c51f5674e9493c7c7163ceaa4ef03d051a31ae3d602d75efee229
[root@localhost opt]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
c0cb5c27515c paigeeworld/centos7 "/bin/bash -c 'while…" 6 seconds ago Up 5 seconds bold_gauss
- 导出、导入容器
[root@localhost opt]# docker export 3d4ba4ddf5c0 > nginx_c //导出容器
[root@localhost opt]# ls
nginx_c rh
[root@localhost opt]# cat nginx_c | docker import - nginx:web //导入容器,会生成镜像而不会创建容器
3.批量删除操作
docker kill $(docker ps -a -q) //杀死所有正在运行的容器
docker rm $(docker ps -a -q) //删除所有已经停止的容器
docker rmi $(docker images -q -f dangling=true) //删除所有未打 dangling 标签的镜像
docker rmi $(docker images -q) //删除所有镜像
docker rmi --force $(docker images | grep doss-api | awk '{print $3}') //强制删除镜像名称中包含“doss-api”的镜像
docker rmi --force $(docker images | awk '{print $3}') //强制删除镜像
docker ps -a | awk '{print "docker rm "$1}' | bash //批量删除容器
docker ps -a | awk '{print "docker stop "$1}'| bash //批量停止容器