官网:Docker: Accelerated Container Application Development
文档地址:Docker Docs
百度百科:Docker_百度百科
0、docker能干嘛?
虚拟机技术:
虚拟机技术缺点:
- 资源占用多
- 冗余步骤多
- 启动很慢
容器技术:
比较docker 和 虚拟机技术不同
- 传统虚拟机:虚拟出一条硬件,运行一个完整的操作系统,然后在这个系统上安装和运行软件
- 容器内的应用直接运行在 宿主机 内核上,容器是没有自己的内核的,也没有虚拟硬件,所以就轻便了
- 每个容器间互相隔离,每个容器内有自己的文件系统,互不影响
应用更快速的交付和部署
传统:一堆帮助文档,安装程序
docker:打包镜像发布测试,一键运行
更便捷的升级和扩缩容
使用了docker之后,我们部署应用就像搭积木一样
项目打包为一个镜像,带着环境直接一键运行,扩展服务器A,服务器B
更简单的系统运维
在容器化之后, 我们的开发,测试环境都是高度一致的
更高效的计算资源利用
1核2g的服务器。docker是内核 级别的 虚拟化。可以在一个物理机上可以运行很多的容器实例。服务器的性能可以被压缩到极致。
一 、docker安装
docker基本组成
镜像(images):
docker镜像就好比一个模板,可以通过这个模板来创建容器服务,tomcat镜像==》run==>tomcat01容器(提供服务器),通过这个镜像可以创建多个容器(最终服务运行或者项目运行就是在容器中的)。
容器(container):
docker利用容器技术,独立运行一个或者一组应用,通过镜像来创建的。
启动,停止,删除,基本命令!
目前就可以把这个容器理解为一个简易的Linux系统
仓库(repository):
就是存放镜像的地方。
仓库分为公有仓库和私有仓库。
docker hub(默认是国外的)
阿里云……都有容器服务器(配置镜像加速)
安装docker
环境准备
- Linux基础
- centos7 / ubuntu
- xshell链接远程服务器进行操作
安装
帮助文档:
安装到centos上:
Install Docker Engine on CentOS | Docker Documentation
安装到Ubuntu上:
Install Docker Engine on Ubuntu | Docker Docs
centos 安装步骤:
1、卸载旧docker版本
yum remove docker \
docker-client \
docker-client-latest \
docker-common \
docker-latest \
docker-latest-logrotate \
docker-logrotate \
docker-engine
2、需要的安装包
yum install -y yum-utils
3、设置镜像仓库
yum-config-manager \
--add-repo \
https://download.docker.com/linux/centos/docker-ce.repo # 默认是国外的
# 推荐使用阿里云的2023-11-8没用了用上面的
yum-config-manager \
--add-repo \
http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo # 推荐使用阿里云的
# 更新yum软件包索引
yum makecache fast
4、安装docker相关的 docker-ce 社区版 ee 企业版
yum install docker-ce docker-ce-cli containerd.io docker-compose-plugin
5、启动docker
systemctl start docker
6、使用docker version 查看是否安装成功
docker version
7、hello-world
sudo docker run hello-world
8、查看一下下载的 hello-world 镜像
docker images
[root@10 ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
hello-world latest feb5d9fea6a5 13 months ago 13.3kB
Ubuntu安装docker
# Add Docker's official GPG key:
sudo apt-get update
sudo apt-get install ca-certificates curl
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc
# Add the repository to Apt sources:
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu \
$(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt-get update
回顾hello-world流程
底层原理
docker是怎么工作的?
docker是一个client-server结构的系统,docker的守护进程运行在主机上,通过socket从客户端访问!
docker-server 接受到 docker-client的指令,就会执行这个指令
docker 为什么 比 vm 快?
- docker 比 虚拟机更少的抽象层
- docker利用的是宿主机的内核,vm需要是guest OS
- 所以说,新建一个容器的时候,docker不需要像虚拟机一样重新加载一个操作系统内核,避免引导。虚拟机是加载guest OS,分钟级别的,docker是利用宿主机的操作系统,省略了这个复杂的过程,秒级的
二、docker常用命令
2.1 帮助命令
帮助文档的地址:docker info | Docker Documentation
docker version # 显示docker版本信息
docker info # 显示docker系统信息,包括镜像和容器的数量
docker 命令 --help # 帮助命令
docker --help # 查看docker所有命令
2.2 镜像命令
docker images 查看本机上的 镜像
docker images | Docker Documentation
[root@10 ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
hello-world latest feb5d9fea6a5 13 months ago 13.3kB
# 解释
REPOSITORY 镜像的仓库源
TAG 镜像的标签
IMAGE ID 镜像的ID
CREATED 镜像的创建时间
SIZE 镜像的大小
# 可选项
[root@10 ~]# docker images --help
Usage: docker images [OPTIONS] [REPOSITORY[:TAG]]
List images
Options:
-a, --all # 列出所有的镜像
-q, --quiet # 只显示镜像的ID
docker search 搜索镜像
[root@10 ~]# docker search mysql
docker pull 下载镜像
[root@10 ~]# docker pull mysql
Using default tag: latest # 如果不写tag,默认就是 latest
latest: Pulling from library/mysql
feec22b5b798: Pull complete # 分层下载, docker image 的核心
Digest: sha256:717e6f25ed8997b7ecb0408e063c4dcba202a68b341ebac4c4d97f51439b87ee # 签名
Status: Downloaded newer image for mysql:latest
docker.io/library/mysql:latest # 真实地址
# 等价 命令
docker pull mysql
docker pull docker.io/library/mysql:latest
# 指定版本下载
[root@10 ~]# docker pull mysql:5.7
docker rmi 删除镜像
[root@10 ~]# docker rmi -f 镜像id # 删除指定的镜像
[root@10 ~]# docker rmi -f 镜像id 镜像id 镜像id # 删除多个镜像
[root@10 ~]# docker rmi -f $(docker images -aq) # 删除全部的镜像
2.3 容器命令
说明:有了镜像才可以创建容器,Linux,下载一个centos镜像测试学习
sudo docker pull centos
[root@sheng bin]# docker pull centos
新建容器并启动
docker run [可选参数] image名
# 参数说明
--name="Tomcat" 容器名字 tomcat01 tomcat02 用来区分容器
-d 后台方式运行
-it 使用交互方式运行,进入容器查看内容
-p 指定容器的端口 -p 8080:8080
-p ip:主机端口:容器端口
-p 主机端口:容器端口 (常用)
-p 容器端口
-P(大P) 随机指定端口
# 测试 : 启动并进入到容器
[root@10 ~]# sudo docker run -it centos /bin/bash
[root@d6c0e889787c /]# ls # 查看容器 内部的centos,基础版本,很多命令都是不完善的!
bin dev etc home lib lib64 lost+found media mnt opt proc root run sbin srv sys tmp usr var
# 从容器中退回到主机
[root@d6c0e889787c /]# exit
exit
[root@10 ~]# ls
anaconda-ks.cfg
列出什么容器在运行
docker ps 命令 # 列出当前正在运行的容器
-a # 列出当前正在运行的容器 + 带出历史运行过的容器
-n=? # 显示最近创建的容器
-q # 只显示容器的 id
[root@10 ~]# sudo docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
[root@10 ~]# sudo docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
d6c0e889787c centos "/bin/bash" 4 minutes ago Exited (0) About a minute ago serene_ride
ee09f5dd6bb9 feb5d9fea6a5 "/hello" About an hour ago Exited (0) About an hour ago pedantic_beaver
退出容器
exit # 直接停止容器并退出
CTRL + p, ctrl + q # 不停止容器退出
删除容器
docker rm 容器id # 删除指定的容器 不能删除正在运行的容器 ,如果要强制删除 rm -f
docker rm -f $(docker ps -aq) # 删除所有的容器
docker ps -aq|xargs docker rm # 删除所有的容器
启动和停止容器的操作
docker start 容器id # 启动容器
docker restart 容器id # 重启容器
docker stop 容器id # 停止当前正在运行的容器
docker kill 容器id # 强制停止当前容器
2.4 常用的其他命令
后台启动容器
# 命令 docker run -d 镜像名
[root@10 ~]# sudo docker run -d centos
# 问题 docker ps 发现 centos 停止了
# 常见的坑:docker 容器使用后台运行,就必须要有一个前台进程,docker发现没有应用,就会自动停止
# nginx 容器启动后,发现自己没有提供服务,就会立即停止,就是没有程序了
查看日志
sudo docker logs -f -t --tail 容器,没有日志
[root@10 ~]# docker run -d centos /bin/sh -c "while true;do echo sheng;sleep 1;done"
# 显示日志
-tf # 显示日志
--tail num # 要显示的日志条数
[root@10 ~]# docker logs -tf --tail 10 fa9fae2c8b3c
查看容器中的进程信息
# 命令 docker top 容器id
[root@10 ~]# docker top fa9fae2c8b3c
UID PID PPID C STIME TTY TIME CMD
root 18476 18457 0 17:04 ? 00:00:00 /bin/sh -c while true;do echo sheng;sleep 1;done
root 18857 18476 0 17:09 ? 00:00:00 /usr/bin/coreutils --coreutils-prog-shebang=sleep /usr/bin/sleep 1
查看镜像的元数据
命令: docker inspect 容器id
# 测试
[root@10 ~]# sudo docker inspect fa9fae2c8b3c
进入当前正在运行的容器
sudo docker logs -f -t --tail 容器,没有日志
[root@10 ~]# docker run -d centos /bin/sh -c "while true;do echo sheng;sleep 1;done"
# 显示日志
-tf # 显示日志
--tail num # 要显示的日志条数
[root@10 ~]# docker logs -tf --tail 10 fa9fae2c8b3c
从容器内拷贝文件的到主机上
docker cp 容器id:容器内路径 目的的主机路径
# 测试
# 查看当前主机目录下
[root@10 home]# ls
sheng.java
[root@10 home]# sudo docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
fab92260a970 centos "/bin/bash" About a minute ago Up About a minute angry_mahavira
# 进入到docker容器内部
[root@10 home]# docker attach fab92260a970
[root@fab92260a970 /]#
[root@fab92260a970 /]# cd /home
[root@fab92260a970 home]# ls
# 在容器内新建一个文件
[root@fab92260a970 home]# touch test.java
[root@fab92260a970 home]# ls
test.java
[root@fab92260a970 home]# exit
exit
[root@10 home]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
[root@10 home]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
fab92260a970 centos "/bin/bash" 2 minutes ago Exited (0) 8 seconds ago angry_mahavira
# 将这个文件拷贝到主机上面
[root@10 home]# docker cp fab92260a970:/home/test.java /home
[root@10 home]# ls
sheng.java test.java
[root@10 home]#
# 拷贝是一个手动过程,未来我们使用-v 卷的技术,可以实现
2.5 小结
attach : ##进入指定运行对象
build : ##通过Dockerfile定制镜像
commit : ##提交当前容器为新的镜像
cp : ##拷贝指定文件或目录到主机
[root@VM-0-9-centos ~]# docker cp 容器id:/home/test.java /home/test_docker_cp/
create : ##创建新的容器,类似于run,但是不启动容器
[root@VM-0-9-centos ~]# docker create centos /bin/bash
diff: ##查看docker容器变化
events: ##从docker获取实时容器事件
exec: ##进入已经启动的容器运行指令
[root@VM-0-9-centos ~]# docker exec -it 容器ID /bin/bash
export: ##到处容器的内容归为一个tar文档
history: ##展示一个镜像形成历史
images: ##列出系统当前镜像
[root@VM-0-9-centos ~]# docker images -a
import: ## 从tar包中内容中创建一个新的文件系统
info: ## 查看系统详细信息
[root@VM-0-9-centos ~]# docker info
inspect: ## 查看容器详细信息
[root@VM-0-9-centos ~]# docker inspect 容器ID
kill: ## 强制结束指定容器
load: ## 从一个tar包中加载一个镜像
login: ## 注册或者登录一个docker源服务器
logout: ## 登出
logs: ## 输出当前容器日志信息
docker logs -tf 容器id
docker logs --tail number 容器id #num为要显示的日志条数
port: ## 查看映射端口对应容器内部的源端口
pasue: ## 暂停容器
ps: ## 列出容器列表
docker ps #运行中列表
docker ps -a #所有容器列表
pull: ## 从docker源镜像拉取指定镜像
docker pull mysql #默认拉取最新版本mysql
push: ## 推送指定镜像或库镜像至docker源服务器
restart: ## 重启正在运行的容器
rm: ## 移除一个或者多个容器
docker rm -f $(docker ps -aq) #移除所有容器
rmi: ## 移除一个或者多个镜像
run: ## 创建一个容器并运行内容
docker run -it centos /bin/bash
save: ## 保存一个镜像为一个tar包
search: ## 在docker hub中搜索镜像
docker search mysql #搜索所有mysql镜像
docker search mysql --filter=STARS=3000 #搜索收藏数大于3000的镜像
start: ## 启动容器
docker start [id]
stop: ## 停止容器
docker stop [id]
tag: ## 给源服务器中镜像设置标签
top: ## 查看容器中运行的进程信息
unpause: ## 取消暂停容器
version: ## 查看docker版本号
docker version
wait: ## 截取容器停止时的退出状态值
2.6 练习
部署nginx
# 1、搜索镜像 search 建议dockerhub 搜索,可以看到帮助文档
# 2、下载镜像 pull
# 3、运行测试
[root@10 home]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
nginx latest 76c69feac34e 11 days ago 142MB
centos latest 5d0da3dc9764 13 months ago 231MB
-d 后台运行
--name 给容器命名
-p 宿主机端口:容器内部端口
[root@10 home]# sudo docker run -d --name nginx01 -p 80:80 nginx
e1cf414bd3e139e8777070f23f5fcfc0717fc265b5a6b1a69cbdd1076c370852
[root@10 home]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
e1cf414bd3e1 nginx "/docker-entrypoint.…" 5 seconds ago Up 4 seconds 0.0.0.0:3344->80/tcp, :::3344->80/tcp nginx01
# 本地访问
[root@10 home]# curl localhost:80
<!DOCTYPE html>
……
# 进入容器
[root@10 home]# sudo docker exec -it nginx01 /bin/bash
root@1ec74fd45eb5:/# whereis nginx
nginx: /usr/sbin/nginx /usr/lib/nginx /etc/nginx /usr/share/nginx
root@1ec74fd45eb5:/# cd /etc/nginx/
root@1ec74fd45eb5:/etc/nginx# ls
conf.d fastcgi_params mime.types modules nginx.conf scgi_params uwsgi_params
思考:每次改动nginx配置文件,都需要进入到容器内部,十分的麻烦,要是可以在容器外部提供一个映射路径,达到在容器修改文件名,容器内部可以自动修改? -v 卷的技术
部署tomcat
# 官方的使用 - 不推荐(用来测试)
docker run -it --rm tomcat:9.0
# 我们之前的启动都是后台,停止了容器之后,容器还可以查到 docker run -it --rm tomcat:9.0 一般用来测试,用完就删除
# 下载再启动
docker pull tomcat
# 启动运行
sudo docker run -d -p 3355:8080 --name tomcat01 tomcat
sudo docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
43eb84edf056 tomcat "catalina.sh run" 57 seconds ago Up 56 seconds 0.0.0.0:3355->8080/tcp, :::3355->8080/tcp tomcat01
# 进入容器
sudo docker exec -it tomcat01 /bin/bash
# 发现问题:1、linux命令少了 2、没有webapps 阿里云镜像的原因,默认是最小的镜像,所有不必要的都剔除掉
# 保证最小的可运行的环境
部署jenkins
# 测试
[root@10 home]# sudo docker run -p 8080:8080 -p 50000:50000 jenkins/jenkins:lts
部署mysql
1、搜索mysql
[root@sheng home]# docker search mysql
NAME DESCRIPTION STARS OFFICIAL AUTOMATED
mysql MySQL is a widely used, open-source relation… 13440 [OK]
mariadb MariaDB Server is a high performing open sou… 5123 [OK]
phpmyadmin phpMyAdmin - A web interface for MySQL and M… 676 [OK]
2、下载MySQL
[root@sheng home]# docker pull mysql:5.7
3、创建并运行容器
docker run -d -p 3306:3306 -e MYSQL_ROOT_PASSWORD=123456 --name mysql5.7 eef0fab001e8
4、使用sqlyog链接即可
可视化portainer
docker run -d -p 9000:9000 -p 8000:8000 \
--restart always -v /var/run/docker.sock:/var/run/docker.sock -v /home/username/portainer/data:/data portainer/portainer
三、docker镜像讲解
3.1 镜像 是什么
镜像是一种轻量级,可执行的独立软件包,用来打包软件运行环境和基于运行环境开发的软件,它包含运行某个软件所需的所有内容,包括代码,运行时,库,环境变量和配置文件
所有的应用,直接打包成docker镜像,就可以直接跑起来。
如何得到镜像呢?
从远程仓库下载
朋友拷贝给你
自己制作一个镜像 DockerFile
3.2 Docker镜像加载原理
UnionFs -> 联合文件系统
下载的时候 看到的一层一层的就是这个!
是一种分层、轻量级并且高性能的文件系统,它支持对文件系统的修改,作为一次提交来一层层的叠加,同时可以将不同目录挂载到同一个虚拟文件系统下(unite directories into a single virtual filesystem)。
UnionFS是Docker镜像的基础,镜像可以通过分层来继承,基于基础镜像(没有父镜像的镜像),可以制作各种具体的应用镜像
特性一次同时加载多个文件系统,但从外面看起来只能看到一个文件系统,联合加载会把各层文件系统叠加起来,这样最终的文件系统会包含所有底层的文件和目录
例子:比如说 mysql 和 tomcat 都需要 centos 环境,先安装了 mysql ,就有了 centos 的环境,那再安装 tomcat ,就可以共用这一层 centos ,不需要再下载 centos 。
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。
这也就是虚拟机启动是分钟级别而容器是秒级启动的原因所在。
3.3 分层理解
分层的镜像
- 可以观察一下下载一个镜像的时候的日志输出,会发现是一层一层的在下载的
- 如下第一层已经存在,不需要在下载
为什么Docker镜像要采用这种分层的结构呢?
最大的好处莫过于是资源共享了。比方说有多个镜像都从相同的 base 镜像构建而来,那么宿主机只需要在磁盘上保留一份 base 镜像,同时内存中也只需要加载一份 base 镜像,这样就可以为所有的容器服务了,而且镜像的每一层都可以被共享。
我们可以通过 docker inspect 命令从 查看镜像分层
所有的 Docker 镜像都起始于一个基础镜像层,当进行修改或增加新的内容时,就会在当前镜像层之上创建新的镜像层。
第一层镜像:基于 Ubuntu Linux 16.04 创建一个新的镜像;如果在这个镜像中添加 Python 包,就会在基础镜像层上创建第二个镜像层;
如果继续添加一个安全补丁,就会创建第三个镜像层,如下图。
Docker 在 Windows 上仅支持 windows filter 一种存储引擎,该引擎基于 NTFS 文件系统之上实现了分层和 CoW
下图展示了与系统显示相同的三层镜像。所有镜像层堆叠并合并,对外提供统一的视图。
- 特点
- Docker 镜像都是只读的,当容器启动时,一个新的可写层被加载到镜像的顶部
- 这一层就是我们通常说的容器层,容器之下的都叫镜像层
3.4 如何提交自己的镜像
commit镜像
docker commit 提交容器成为一个新的副本
# 命令原理和 git 类似
docker commit -m="提交的描述信息" -a="作者" 容器id 目标镜像名:[TAG]
docker commit 提交容器成为一个新的副本 # 命令原理和 git 类似 docker commit -m="提交的描述信息" -a="作者" 容器id 目标镜像名:[TAG]
实战测试
1、启动一个默认的tomcat
docker run -it --name mytomcat -p 8088:8080 tomcat
2、发现这个默认的tomcat 是没有webapps应用的,镜像的原因,官方的镜像默认 webapps下面是没有文件的
3、进入tomcat01容器 ,自己拷贝进去基本的文件
docker exec -it 1101230e4f3c /bin/bash # 进入容器
cp -r webapps.dist/* webapps # 复制文件到 webapps
4、将修改后的容器 通过commit 提交为一个镜像,以后就使用我们修改后的镜像即可,这就是我们自己的一个修改的镜像
[root@Allen ~]# docker commit -a="sheng" -m="add webapps app" e4febebd2fab mytom:1.0
sha256:d78a4f259eff2b8f1f04d5ed0898079efa07a93215799dce173ef739632511cd
[root@Allen ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
mytom 1.0 d78a4f259eff 5 seconds ago 478MB
tomcat latest 1dad8c5497f9 4 weeks ago 474MB
……
四、容器数据卷
4.1 什么是容器数据卷?
docker 理念回顾
将应用和环境打包成一个镜像!
数据?如果数据都在容器中,那么容器一删除,数据就会丢失!
mysql,容器删了,删库跑路,需求,数据可以持久化
容器之间有一个数据共享的技术,Docker容器中产生的数据,同步到本地
这就是卷技术,目录的挂载,将容器内的目录,挂载到Linux上面
总结一句话:容器的持久化和同步操作!容器间也是可以数据共享的。
4.2 使用数据卷
方式一:直接使用命令来挂载
docker run -it -v 主机目录:容器内目录 -p 主机端口:容器内端口 测试 docker run -it -v /home/ceshi:/home centos bash
docker inspect 04b955f50cef 查看容器详细信息
测试文件的同步
1、 停止容器
2、 宿主机上修改文件
3、 再次启动容器,容器内的数据依然能够同步
好处:我们以后修改只需要在本地修改就可以了,容器内会自动同步
思考:MySQL 的数据持久化的问题