前期准备:
给Ubuntu添加清华的软件源
找到 sources.list 文件
cd /etc/apt/
编辑
vim sources.list
在最后面加上下面这几条语句
# 默认注释了源码镜像以提高 apt update 速度,如有需要可自行取消注释
deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ xenial main restricted universe multiverse
# deb-src https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ xenial main restricted universe multiverse
deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ xenial-updates main restricted universe multiverse
# deb-src https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ xenial-updates main restricted universe multiverse
deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ xenial-backports main restricted universe multiverse
# deb-src https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ xenial-backports main restricted universe multiverse
deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ xenial-security main restricted universe multiverse
# deb-src https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ xenial-security main restricted universe multiverse
然后保存,现在就可以使用新加入的软件源更新软件了,执行 sudo apt update 查看是否有软件需要更新。
1、Docker安装
1.1、docker的架构图
镜像(image):
Docker 镜像(Image)就是一个只读的模板。镜像可以用来创建 Docker 容器,一个镜像可以创建很多容器。 就好似 Java 中的 类和对象,类就是镜像,容器就是对象!
容器(container):
Docker 利用容器(Container)独立运行的一个或一组应用。容器是用镜像创建的运行实例。
它可以被启动、开始、停止、删除。每个容器都是相互隔离的,保证安全的平台。
可以把容器看做是一个简易版的 Linux 环境(包括root用户权限、进程空间、用户空间和网络空间等)和运行在其中的应用程序。
容器的定义和镜像几乎一模一样,也是一堆层的统一视角,唯一区别在于容器的最上面那一层是可读可写的。
仓库(repository):
仓库(Repository)是集中存放镜像文件的场所。
仓库(Repository)和仓库注册服务器(Registry)是有区别的。仓库注册服务器上往往存放着多个仓库,每个仓库中又包含了多个镜像,每个镜像有不同的标签(tag)。
仓库分为公开仓库(Public)和私有仓库(Private)两种形式。
最大的公开仓库是 Docker Hub(https://hub.docker.com/),存放了数量庞大的镜像供用户下载。
国内的公开仓库包括阿里云 、网易云 等。
1.2 docker安装
1)先卸载可能存在的旧版本
sudo apt-get remove docker docker-engine docker.io containerd runc
2)更新apt包索引
sudo apt-get update
3)安装以下包以使apt可以通过HTTPS使用存储库(repository)
sudo apt-get install python3-software-properties
sudo apt-get install apt-transport-https
sudo apt-get install ca-certificates
sudo apt-get install curl
sudo apt-get install gnupg-agent
sudo apt-get install software-properties-common
4)添加Docker官方的GPG密钥
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
5)验证您在是否拥有带有指纹的密钥
sudo apt-key fingerprint 0EBFCD88
6)使用下面的命令来设置stable存储库
sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"
7)再更新一下apt包索引
sudo apt-get update
8)安装最新版本的Docker CE
sudo apt-get install docker-ce
2、Docker常用命令
2.1、帮助命令
docker version # 显示 Docker 版本信息
docker info # 显示 Docker 系统信息,包括镜像和容器数。。
docker --help # 帮助
2.2、镜像命令
docker images
# 列出本地主机上的镜像
[root@kuangshen ~]# docker images
REPOSITORY TAG IMAGE ID CREATED
SIZE
hello-world latest bf756fb1ae65 4 months ago
13.3kB
# 解释
REPOSITORY 镜像的仓库源
TAG 镜像的标签
IMAGE ID 镜像的ID
CREATED 镜像创建时间
SIZE 镜像大小
# 同一个仓库源可以有多个 TAG,代表这个仓库源的不同版本,我们使用REPOSITORY:TAG 定义不同
的镜像,如果你不定义镜像的标签版本,docker将默认使用 lastest 镜像!
# 可选项
-a: 列出本地所有镜像
-q: 只显示镜像id
--digests: 显示镜像的摘要信息
docker search
# 搜索镜像
[root@kuangshen ~]# docker search mysql
NAME DESCRIPTION
OFFICIAL
mysql MySQL is a widely used, open-source relation…
[OK]
# docker search 某个镜像的名称 对应DockerHub仓库中的镜像
# 可选项
--filter=stars=50 : 列出收藏数不小于指定值的镜像。
docker pull
# 下载镜像
[root@kuangshen ~]# docker pull mysql
docker rmi
# 删除镜像
docker rmi -f 镜像id # 删除单个
docker rmi -f 镜像名:tag 镜像名:tag # 删除多个
docker rmi -f $(docker images -qa) # 删除全部
2.3、容器命令
说明:有镜像才能创建容器,我们这里使用 ubuntu 的镜像来测试,就是虚拟一个ubuntu !
#拉取最新的 ubuntu:18.04 镜像
sudo docker pull ubuntu:18.04
#查看镜像
docker images
#新建容器并启动
docker run [OPTIONS] IMAGE [COMMAND][ARG...]
# 常用参数说明
--name="Name" # 给容器指定一个名字
-d # 后台方式运行容器,并返回容器的id!
-i # 以交互模式运行容器,通过和 -t 一起使用
-t # 给容器重新分配一个终端,通常和 -i 一起使用
-P # 随机端口映射(大写)
-p # 指定端口映射(小结),一般可以有四种写法
ip:hostPort:containerPort
ip::containerPort
hostPort:containerPort (常用)
containerPort
# 测试
root@test-virtual-machine:/opt# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
ubuntu 18.04 5a214d77f5d7 3 months ago 63.1MB
# 使用centos进行用交互模式启动容器,在容器内执行/bin/bash命令!
[root@kuangshen ~]# docker run -it ubuntu:18.04 /bin/bash
[root@dc8f24dd06d0 /]# ls # 注意地址,已经切换到容器内部了!
bin etc lib lost+found mnt proc run srv tmp var
dev home lib64 media opt root sbin sys usr
列出所有运行的容器
# 命令 |
docker ps [OPTIONS] |
# 常用参数说明 |
-a # 列出当前所有正在运行的容器 + 历史运行过的容器 |
-l # 显示最近创建的容器 |
-n=? # 显示最近n个创建的容器 |
-q # 静默模式,只显示容器编号。 |
退出容器
exit | # 容器停止退出 |
ctrl+P+Q | # 容器不停止退出 |
启动停止容器
docker | start (容器id or 容器名) | # | 启动容器 |
docker | restart (容器id or 容器名) | # | 重启容器 |
docker | stop (容器id or 容器名) | # | 停止容器 |
docker | kill (容器id or 容器名) | # | 强制停止容器 |
删除容器
docker rm 容器id | # 删除指定容器 |
docker rm -f $(docker ps -a -q) | # 删除所有容器 |
docker ps -a -q|xargs docker rm | # 删除所有容器 |
2.3、常用其他命令
后台启动容器
# 命令 |
docker run -d 容器名 |
# 例子 |
docker run -d ubuntu:18.04 # 启动ubuntu,使用后台方式启动 |
# 问题: 使用docker ps 查看,发现容器已经退出了! |
# 解释:Docker容器后台运行,就必须有一个前台进程,容器运行的命令如果不是那些一直挂起的命 |
令,就会自动退出。 |
# 比如,你运行了nginx服务,但是docker前台没有运行应用,这种情况下,容器启动后,会立即自 |
杀,因为他觉得没有程序了,所以最好的情况是,将你的应用使用前台进程的方式运行启动。 |
查看日志
# 命令 |
docker logs -f -t --tail=100 容器id |
# 例子:我们启动 ubuntu,并编写一段脚本来测试玩玩!最后查看日志 |
[root@kuangshen ~]# docker run -itd ubuntu:18.04 /bin/sh -c "while true;do echo kuangshen;sleep 1;done" |
[root@kuangshen ~]# docker ps |
CONTAINER ID IMAGE |
c8530dbbe3b4 ubuntu |
# -t 显示时间戳 |
# -f 打印最新的日志 |
# --tail 数字 显示多少条! |
[root@kuangshen ~]# docker logs -tf --tail 10 c8530dbbe3b4 |
2020-05-11T08:46:40.656901941Z kuangshen |
2020-05-11T08:46:41.658765018Z kuangshen |
2020-05-11T08:46:42.661015375Z kuangshen |
2020-05-11T08:46:43.662865628Z kuangshen |
2020-05-11T08:46:44.664571547Z kuangshen |
2020-05-11T08:46:45.666718583Z kuangshen |
2020-05-11T08:46:46.668556725Z kuangshen |
2020-05-11T08:46:47.670424699Z kuangshen |
2020-05-11T08:46:48.672324512Z kuangshen |
2020-05-11T08:46:49.674092766Z kuangshen |
查看容器中运行的进程信息,支持 ps 命令参数
# 命令 |
docker top 容器id |
# 测试 |
[root@kuangshen ~]# docker top c8530dbbe3b4 |
UID PID PPID C STIME TTY TIME CMD |
root 66854 66826 0 17:52 pts/0 00:00:00 /bin/bash |
查看容器/镜像的元数据
# 命令 |
docker inspect 容器id |
进入正在运行的容器
# 命令1 |
docker exec -it 容器id bashShell |
# 命令2 |
docker attach 容器id |
# 区别 |
#exec 是在容器中打开新的终端,并且可以启动新的进程 |
#attach 直接进入容器启动命令的终端,不会启动新的进程 |
从容器内拷贝文件到主机上
# 命令 |
docker cp 容器id:容器内路径 目的主机路径 |
小结:
练习:
1、使用Docker 安装 Nginx
# 1、搜索镜像 | ||
[root@kuangshen ~]# docker search nginx | ||
NAME DESCRIPTION | STARS | OFFICIAL |
nginx Official build of Nginx. | 13159 | [OK] |
# 2、拉取镜像 | ||
[root@kuangshen ~]# docker pull nginx | ||
Using default tag: latest |
latest: Pulling from library/nginx |
54fec2fa59d0: Pull complete |
4ede6f09aefe: Pull complete |
f9dc69acb465: Pull complete |
Digest: |
sha256:86ae264c3f4acb99b2dee4d0098c40cb8c46dcf9e1148f05d3a51c4df6758c12 |
Status: Downloaded newer image for nginx:latest |
docker.io/library/nginx:latest |
# 3、启动容器 |
[root@kuangshen ~]# docker images |
REPOSITORY TAG IMAGE ID CREATED |
SIZE |
diytomcat latest ffdf6529937d 3 hours ago |
636MB |
nginx latest 602e111c06b6 2 weeks ago |
127MB |
centos latest 470671670cac 3 months ago |
237MB |
[root@kuangshen ~]# docker run -d --name mynginx -p 3500:80 nginx |
a95d5f2f057fc609082cfa0de906bd690f95c43a26d38420d081f0e255b232ec |
[root@kuangshen ~]# docker ps |
CONTAINER ID IMAGE PORTS NAMES |
a95d5f2f057f nginx 0.0.0.0:3500->80/tcp mynginx |
# 4、测试访问 |
[root@kuangshen ~]# curl localhost:3500 |
<html> |
<title>Welcome to nginx!</title> # ok |
.... |
</html> |
# 5、进入容器 |
[root@kuangshen ~]# docker exec -it mynginx /bin/bash |
root@a95d5f2f057f:/# whereis nginx # 寻找nginx |
nginx: /usr/sbin/nginx /usr/lib/nginx /etc/nginx /usr/share/nginx |
root@a95d5f2f057f:/# cd /usr/share/nginx # nginx 的路径 |
root@a95d5f2f057f:/usr/share/nginx# ls |
html |
root@a95d5f2f057f:/usr/share/nginx# cd html # 首页的位置 |
root@a95d5f2f057f:/usr/share/nginx/html# ls |
50x.html index.html |
root@a95d5f2f057f:/usr/share/nginx/html# cat index.html |
<!DOCTYPE html> |
<html> |
<head> |
<title>Welcome to nginx!</title> |
<style> |
body { |
width: 35em; |
margin: 0 auto; |
font-family: Tahoma, Verdana, Arial, sans-serif; |
} |
</style> |
</head> |
<body> |
<h1>Welcome to nginx!</h1> |
</html> |
2、使用docker安装 tomcat
# 官方文档解释 |
# -it :交互模式 |
# --rm:容器启动成功并退出以后容器就自动移除,一般在测试情况下使用! |
docker run -it --rm tomcat:9.0 |
# 1、下载tomcat镜像 |
docker pull tomcat |
# 2、启动 |
docker run -d -p 8080:8080 --name tomcat9 tomcat |
# 3、进入tomcat |
docker exec -it tomcat9 /bin/bash |
# 4、思考:我们以后要部署项目,还需要进入容器中,是不是十分麻烦,要是有一种技术,可以将容器 |
内和我们Linux进行映射挂载就好了?我们后面会将数据卷技术来进行挂载操作,也是一个核心内容,这 |
里大家先听听名词就好,我们很快就会讲到! |
Docker镜像讲解
镜像是什么
镜像是一种轻量级、可执行的独立软件包,用来打包软件运行环境和基于运行环境开发的软件,它包含 运行某个软件所需的所有内容,包括代码、运行时、库、环境变量和配置文件。
Docker镜像加载原理
UnionFS (联合文件系统)
UnionFS(联合文件系统):Union文件系统(UnionFS)是一种分层、轻量级并且高性能的文件系统, 它支持对文件系统的修改作为一次提交来一层层的叠加,同时可以将不同目录挂载到同一个虚拟文件系 统下(unite several directories into a single virtual filesystem)。Union 文件系统是 Docker 镜像的基础。镜像可以通过分层来进行继承,基于基础镜像(没有父镜像),可以制作各种具体的应用镜像。
特性:一次同时加载多个文件系统,但从外面看起来,只能看到一个文件系统,联合加载会把各层文件 系统叠加起来,这样最终的文件系统会包含所有底层的文件和目录
Docker镜像加载原理
docker的镜像实际上由一层一层的文件系统组成,这种层级的文件系统UnionFS。
bootfs(boot file system)主要包含bootloader和kernel, bootloader主要是引导加载kernel, Linux刚启动时会加载bootfs文件系统,在Docker镜像的最底层是bootfs。这一层与我们典型的Linux/Unix系统是一样的,包含boot加载器和内核。当boot加载完成之后整个内核就都在内存中了,此时内存的使用权已 由bootfs转交给内核,此时系统也会卸载bootfs。
rootfs (root file system) ,在bootfs之上。包含的就是典型 Linux 系统中的 /dev, /proc, /bin, /etc 等标准目录和文件。rootfs就是各种不同的操作系统发行版,比如Ubuntu,Centos等等。
平时我们安装进虚拟机的CentOS都是好几个G,为什么Docker这里才200M?
对于一个精简的OS,rootfs 可以很小,只需要包含最基本的命令,工具和程序库就可以了,因为底层直接用Host的kernel,自己只需要提供rootfs就可以了。由此可见对于不同的linux发行版, bootfs基本是一致的, rootfs会有差别, 因此不同的发行版可以公用bootfs。
分层理解
我们可以去下载一个镜像,注意观察下载的日志输出,可以看到是一层一层的在下载!
思考:为什么Docker镜像要采用这种分层的结构呢?
最大的好处,我觉得莫过于是资源共享了!比如有多个镜像都从相同的Base镜像构建而来,那么宿主机 只需在磁盘上保留一份base镜像,同时内存中也只需要加载一份base镜像,这样就可以为所有的容器服 务了,而且镜像的每一层都可以被共享。
查看镜像分层的方式可以通过 docker image inspect 命令!
理解:
所有的 Docker 镜像都起始于一个基础镜像层,当进行修改或增加新的内容时,就会在当前镜像层之上,创建新的镜像层。
举一个简单的例子,假如基于 Ubuntu Linux 16.04 创建一个新的镜像,这就是新镜像的第一层;如果在该镜像中添加 Python包,就会在基础镜像层之上创建第二个镜像层;如果继续添加一个安全补丁,就会创建第三个镜像层。
该镜像当前已经包含 3 个镜像层,如下图所示(这只是一个用于演示的很简单的例子)。
在添加额外的镜像层的同时,镜像始终保持是当前所有镜像的组合,理解这一点非常重要。下图中举了 一个简单的例子,每个镜像层包含 3 个文件,而镜像包含了来自两个镜像层的 6 个文件。
上图中的镜像层跟之前图中的略有区别,主要目的是便于展示文件。
下图中展示了一个稍微复杂的三层镜像,在外部看来整个镜像只有 6 个文件,这是因为最上层中的文件
7 是文件 5 的一个更新版本。
这种情况下,上层镜像层中的文件覆盖了底层镜像层中的文件。这样就使得文件的更新版本作为一个新 镜像层添加到镜像当中。
Docker 通过存储引擎(新版本采用快照机制)的方式来实现镜像层堆栈,并保证多镜像层对外展示为统一的文件系统。
Linux 上可用的存储引擎有 AUFS、Overlay2、Device Mapper、Btrfs 以及 ZFS。顾名思义,每种存储引擎都基于 Linux 中对应的文件系统或者块设备技术,并且每种存储引擎都有其独有的性能特点。
Docker 在 Windows 上仅支持 windowsfilter 一种存储引擎,该引擎基于 NTFS 文件系统之上实现了分层和 CoW[1]。
下图展示了与系统显示相同的三层镜像。所有镜像层堆叠并合并,对外提供统一的视图。
特点
Docker镜像都是只读的,当容器启动时,一个新的可写层被加载到镜像的顶部! 这一层就是我们通常说的容器层,容器之下的都叫镜像层!
镜像Commit
docker commit 从容器创建一个新的镜像。
docker commit 提交容器副本使之成为一个新的镜像! |
# 语法 |
docker commit -m="提交的描述信息" -a="作者" 容器id 要创建的目标镜像名:[标签名] |
测试
# 1、从Docker Hub 下载tomcat镜像到本地并运行 -it 交互终端 -p 端口映射 |
docker run -it -p 8080:8080 tomcat |
# 注意:坑爹:docker启动官方tomcat镜像的容器,发现404是因为使用了加速器,而加速器里的 |
tomcat的webapps下没有root等文件! |
# 下载tomcat官方镜像,就是这个镜像(阿里云里的tomcat的webapps下没有任何文件) |
# 进入tomcat查看cd到webapps下发现全部空的,反而有个webapps.dist里有对应文件,cp -r |
到webapps下! |
root@aba865b53114:/usr/local/tomcat# cp -r webapps.dist/* webapps |
# 2、删除上一步镜像产生的tomcat容器的文档 |
docker ps # 查看容器id |
docker exec -it 容器id /bin/bash |
/usr/local/tomcat # ce webapps/ |
/usr/local/tomcat/webapps # ls -l # 查看是否存在 docs文件夹 |
/usr/local/tomcat/webapps # curl localhost:8080/docs/ # 可以看到 docs 返回的 |
内容 |
/usr/local/tomcat/webapps # rm -rf docs # 删除它 |
/usr/local/tomcat/webapps # curl localhost:8080/docs/ # 再次访问返回404 |
# 3、当前运行的tomcat实例就是一个没有docs的容器,我们使用它为模板commit一个没有docs的 |
tomcat新镜像, tomcat02 |
docker ps -l # 查看容器的id |
# 注意:commit的时候,容器的名字不能有大写,否则报错:invalid reference format |
docker commit -a="kuangshen" -m="no tomcat docs" 1e98a2f815b0 tomcat02:1.1 |
sha256:cdccd4674f93ad34bf73d9db577a20f027a6d03fd1944dc0e628ee4bf17ec748 |
[root@kuangshen /]# docker images # 查看,我们自己提交的镜像已经OK了! |
REPOSITORY TAG IMAGE ID CREATED |
SIZE |
tomcat02 1.1 cdccd4674f93 About a minute |
ago 649MB |
redis latest f9b990972689 9 days ago |
104MB |
tomcat latest 927899a31456 2 weeks ago |
647MB |
centos latest 470671670cac 3 months ago |
237MB |
# 4、这个时候,我们的镜像都是可以使用的,大家可以启动原来的tomcat,和我们新的tomcat02来 |
测试看看! |
[root@kuangshen ~]# docker run -it -p 8080:8080 tomcat02:1.1 |
# 如果你想要保存你当前的状态,可以通过commit,来提交镜像,方便使用,类似于 VM 中的快照! |