Docker简单入门
前言
1、什么是docker?
- 是一个C/S架构的承载应用运行的平台软件
2、为什么用docker
- 解决应用运行环境配置的复杂性
- 轻量级,内存占用低
- 扩容方便,使用镜像部署效率高,只需要将程序及其所依赖的环境打包成镜像,即可在服务器上将程序及其运行环境一站式部署
3、docker与虚拟机之间的区别
4、docker核心架构
- 镜像:一个镜像代表一个应用环境,他是一个只读的文件,如mysql镜像,tomcat镜像,nginx镜像等
- 容器:镜像每次运行之后就是产生一个容器,就是正在运行的镜像,特点就是可读可写
- 仓库:用来存放镜像的位置,类似于maven仓库,也是镜像下载和上传的位置
- dockerFile:docker生成镜像配置文件,用来书写自定义镜像的一些配置
- tar:一个对镜像打包的文件,日后可以还原成镜像
5、docker镜像原理
镜像是什么?
镜像是一种轻量级的,能够独立执行的软件包,用来打包软件运行环境和基于运行环境开发的软件,包含软件运行所需要的所有内容,包括代码,库,环境变量以及配置文件。
- UnionFS(联合文件系统):
Union文件系统是一种分层,轻量级并具高性能的文件系统,它支持对文件系统的修改作为一次提交来一层层的叠加,同时可以将不同目录挂载到同一个虚拟文件系统下。Union文件系统是Docker镜像的基础。这种文件系统特性:就是一次同时加载多个文件系统,但从外面看起来,只能看到一个文件系统,联合加载会把各层文件系统叠加起来,这样最终的文件系统会包含所有底层的文件和目录。
镜像原理
-
docker的镜像实际是由一层一层的文件系统组成
- bootfs(boot file system)主要包含bootloader和kernel,bootloader主要是引导加载kernel,Linux刚启动时会加载bootfs文件系统。在docker镜像的最底层就是bootfs这一层与Linux/Unix系统是一样的,包含boot加载器(bootloader)和内核(kernel)。当boot加载完后整个内核就都在内存中了,此时内存的使用权已由bootfs转交给内核,此时会卸载bootfs。
- rootfs(root file system),在bootfs之上,包含的就是典型的linux系统中的/dev,/proc,/bin,/etc等标准的目录和文件。rootfs就是各种不同的操作系统发行版,比如Ubuntu/CentOS等等。
- 我们平时安装进虚拟机的centos都有1到几个GB,为什么docker这里才200MB?对于一个精简的os,rootfs可以很小,只需要包括最基本的命令,工具,和程序库就可以了,因为底层直接使用Host的Kernal,自己只需要提供rootfs就行了。由此可见不同的linux发行版,他们的bootfs是一致的,rootfs会有差别。因此不同的发行版可以共用bootfs。
-
为什么docker镜像要采用这种分层结构呢?
- 最大的一个好处就是资源共享
- 比如:有多个镜像都是从相同的base镜像构建而来的,那么宿主机只需在磁盘中保存一份base镜像。同时内存中也
只需要加载一份base镜像
,就可以为所有容器服务了。而且镜像的每一层都可以被共享。Docker镜像都是只读的。当容器启动时,一个新的可写层被加载到镜像的顶部。这一层通常被称为容器层,容器层之下都叫镜像层。
安装
Docker官网 下载链接 官方文档 练习play-with-docker
方式一
# 安装docker依赖
yum install -y yum-utils device-mapper-persistent-data lvm2
# 配置yum依赖设置docker的yum源
yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
# 安装最新版的docker
yum install -y docker-ce docker-ce-cli containelrd.io
# 启动docker
systemctl start docker
systemctl enable docker
# 关闭docker
systemctl stop docker
# 测试docker安装
docker run hello-world
# 安装过程中 docker中报错 failure: repodata/repomd.xml from mirrors.aliyun.com_docker-ce_linux_centos_docker-ce.pro
解决方案
https://blog.csdn.net/qq_18948359/article/details/102715729
指定安装版本
yum list docker-ce --showduplicates | sort -r
sudo yum install docker-ce-<VERSION_STRING> docker-ce-cli-<VERSION_STRING> containerd. io
sudo yum install docker-ce-18.09.5-3.e17 docker-ce-cli-18.09.5-3.e17 containerd.io
方式二
curl -fsSL https://get.docker.com | bash -s docker --mirror Aliyun
配置
1、阿里云镜像仓库
2、配置阿里云加速
sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": ["https://uz579bhl.mirror.aliyuncs.com"]
}
EOF
sudo systemctl daemon-reload
sudo systemctl restart docker
拉取镜像失败参考:https://www.cnblogs.com/hhddd-1024/p/18375560
3、验证配置
docker info
# 出现以下信息则配置成功
Insecure Registries:
127.0.0.0/8
Registry Mirrors:
https://uz579bhl.mirror.aliyuncs.com/
Live Restore Enabled: false
卸载已存在的Docker
sudo yum remove docker docker-client docker-client-latest docker-common docker-latest docker-latest-logrotate docker-logrotate docker-engine
卸载方式二:
https://blog.csdn.net/m0_67390379/article/details/123731952
常用命令
服务命令
# 查看版本
docker version
# 查看详细信息
docker info
# 指令帮助
docker --help
# 启动|停止|重启|状态查询
systemctl start|stop|restart|status docker
镜像命令
# 查看所有镜像
docker images
# 搜索镜像
docker search 镜像名称
# 下载镜像
docker pull 镜像名[:TAG|@DIGEST]
# 上传镜像
docker push 镜像名称
# 备份镜像
docker save 镜像 -o xxx.tar
# 加载备份的镜像
docker load -i xxx.tar
# 查看镜像的制作历史
docker history 镜像
# 检查镜像的详细参数信息
docker inspect 镜像
# 给镜像改名字及tag标签
docker tag 镜像 名称
# 删除镜像
docker rmi 镜像 # 删除
docker rmi -f 镜像 # 强制删除
# 删除所有镜像
docker rmi -f $(docker images -qa)
# 删除所有没打标签的镜像
docker rmi -f $(docker images -q | awk '/^<none>/ { print $3 }')
# 删除所有包含关键字的镜像
docker rmi --force [-f] $(docker images | grep 尽量准确的关键字 | awk '{print $3}')
# 显示所有虚镜像
docker image ls -f dangling=true
# 删除REPOSITORY、TAG为none的镜像(虚悬镜像)
docker rmi $(docker images -q -f dangling=true)
容器命令
基本命令(容器外直接执行)
# 运行一个容器
docker run --help
# 例如
docker run -it --name myNginx -p 80:80 nginx
docker run -d --name myNginx -P nginx
# 查看容器
docker ps --help
docker ps -a
# 停止|关闭|重启容器
docker start 容器
docker restart 容器
docker stop 容器
docker kill 容器
# 查看容器内进程
docker top 容器
# 查看容器内部细节
docker inspect
# 查看容器的运行日志
docker logs [OPTIONS] 容器
-f 查看实时日志
--tail 查看后10条日志
# 删除一个容器
docker rm -f 容器
# 删除所有状态为 Exited 的容器
docker rm $(docker ps -qf status=exited)
# 删除所有容器
docker rm -f $(docker ps -aq)
容器内数据交互命令
# 1.在宿主机发送命令到容器内部执行
docker exec -it 容器 命令
-i # 以交互模式运行容器,通常与-t一起使用
-t # 分配一个伪终端
# 进入容器内部
# 注意:这里要理解bash,sh这些终端其实也是命令(等同于ls,pwd等等),只是导致的结果是进入了终端
docker exec -it 容器 命令(bash/sh...)
# 以root用户发送命令到容器内部并执行
docker exec -it -u root 容器 命令(bash/sh...)
# 2.容器内安装软件(前提是在容器的bash里执行)
apt-get update
apt-get install 安装包
# 3.退出容器
exit
# 4.将容器打包为新的镜像
docker commit -a "作者名称" -m "描述信息" 容器ID 目标镜像名称:TAG
# 5.上传文件到容器
docker cp 宿主机文件绝对路径 容器:容器路径
# 6.从容器下载文件到宿主机
docker cp 容器:容器内文件绝对路径 宿主机路径
# 7.检查容器详细参数
docker inspect 容器
# 7.设置容器和宿主机共享目录(数据卷valueme)
docker run -it -v /宿主机文件/文件夹绝对路径:/容器内绝对路径:ro(只读) 镜像
# 例如:docker run -d --name "nginx" -p 80:80 -v /root/test/:/usr/share/nginx/html:ro nginx
# docker inspect nginx
"Mounts" : [
{
"Type": "bind",
"Source": "/root/test", // 宿主机绝对路径
"Destination": "/usr/share/nginx/html", // 容器内绝对路径
"Mode": "ro", // only read 只读
"RW": false,
"Propagation": "rprivate"
}
]
Docker中安装常用软件
☆docker可视化工具Portainer部署与汉化
# 1、搜索镜像
docker search portainer
# 2、下载最高start
docker pull portainer/portainer
# 3、部署单机版仅本机能访问,命令如下
docker run -d -p 9000:9000 --restart=always -v /var/run/docker.sock:/var/run/docker.sock -v portainer_data:/data --name prtainer portainer/portainer
下载portainer汉化包 (提取码:6vjr)
# 解压
tar -xvf public.tar
# 将public移动到根目录
mv public /
# 部署汉化版portainer
docker run -d -p 9000:9000 --restart=always -v /var/run/docker.sock:/var/run/docker.sock -v portainer_data:/data -v /public:/public --name prtainer-test portainer/portainer
安装mysql数据库
# 1、安装mysql
docker pull mysql:TAG
# 2、启动mysql
docker run --name mysql -e MYSQL_ROOT_PASSWORD="root用户的密码" -d -p 3306:3306 mysql:TAG
可能出现的问题
# 3.进入mysq1容器
docker exec -it mysql bash
# 4.查看mysq1日志
docker logs -f mysql
# 5.使用自定义配置参数
docker run --name mysql -v /root/mysql/conf.d:/etc/mysq1/conf.d -e MYSQL_ROOT_PASSWORD=root -d mysq1:TAG
# 6.将容器数据位置与宿主机位置挂载保证数据安全
docker run --name mysql -p 3306:3306 -d -v /root/mysq1/data:/var/lib/mysql
-v /root/mysq1/conf.d:/etc/mysq1/conf.d -e MYSQL_PASSWOT_PASSWORD=root mysql:TAG
# 7.访问测试
# 8.数据备份
# 导出全部数据
docker exec mysql sh -c 'exec mysqldump --all-databases -uroot -p"$MYSQL_ROOT_PASSWORD"' > /root/sql.sql
# 导出指定库的数据
docker exec mysql sh -c 'exec mysqldump --databases 库表 -uroot -p"$MYSQL_ROOT_PASSWORD"' > /root/sql.sql
# 导出指定库数据不要
docker exec mysql sh -c 'exec mysqldump --no-data --databases 库表 -uroot -p"$MYSQL_ROOT_PASSWORD"' > /root/all-databases.sql
# 9.执行sq1文件到mysq1中
docker exec -i mysql sh -c 'exec mysql -uroot -p"$MYSQL_ROOT_PASSWORD"' < /root/sql.sq1
安装redis服务
# 1、搜索镜像
docker search redis
# 2、拉取下载
docker pull redis:TAG
# 3、启动
docker -d -p 3306:3306 --name redis redis:TAG
# 4、查看启动日志
docker logs -f redis
# 5、进入容易内部操作
docker exec -it redis /bin/bash
# 6.挂载外部自定义配置启动redis容器
# 默认情况下redis官方镜像中没有redis.conf配置文件需要去官网下载指定版本的配置文件
# 6.1 wgethttp://download.redis.io/releases/redis-5.0.8.tar.gz下载官方安装包
# 6.2 将官方安装包中配置文件进行复制到宿主机指定目录中如/root/redis/redis.conf文件
# 6.3 修改需要自定义的配置
# bind0.0.0.0开启远程权限
# 默认是rdb持久化模式
# appenonly yes开启aof持久化,每秒同步一次
docker run -v /root/myredis/conf:/usr/local/etc/redis --name redis -d -p 6379:6379 redis redis-server /usr/local/etc/redis/redis.conf
# 7.将数据目录挂载宿主机保证数据安全
docker run --name redis -v /root/redis/data:/data -v /root/myredis/conf:/usr/local/etc/redis -d -p 6379:6379 redis redis-server /usr/local/etc/redis/redis.conf
springboot中使用redis
1、引入操作redis依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
2、通过上述导入的依赖提供的RedisTemplete(操作对象)或者StringRedisTemplete(主要操作字符串)操作redis数据库,使用了模板方法设计模式。
3、application.xml配置redis数据库,主机、端口、数据库
4、注意点
- RedisTemplete持久化对象时,目标对象需实现序列化接口
- 设置键的序列化方式为Stirng的方式
- 值的序列化方式一般设置为json序列化
安装tomcat应用服务器
# 搜索镜像
docker search
# 拉取镜像
docker pull tomcat:tag
# 以用完即删的方式运行
docker run --rm
# 挂载tomcat的webapps目录到宿主机中运行
docker run --rm -d -p 8888:8080 -v /root/tomcat/webapps:/usr/local/tomcat/webapps tomcat:9.0
安装Mongo
- 注意身份验证的问题
安装ElasticSearch分布式搜索引擎
- 拉取镜像
- 配置linux虚拟机:配置JVM
- 启动ElasticSearch
- 安装IK分词器
- 安装Kibana
Docker与集群管理工具Swarm
引言
Swarm是Docker官方提供的一款集群管理工具,其主要作用是把若干台Docker主机抽象为一个整体,并且通过一个入口统一管理这些Docker主机上的各种Docker资源。
DockerFile
什么是DockerFile?
- 是Docker镜像的描述文件,是有一系列命令及参数构成的脚本,用来自定义镜像的构建文件。
DockerFile保留指令集
构建第一个DockerFile
# 1、创建DockerFile
echo "FROM nginx" > Dockerfile
echo "RUN echo 你好RUN" >> Dockerfile
echo "CMD echo 你好CMD" >> Dockerfile
# 2、构建
docker build -t 镜像[:tag] .
# 3、查看
docker images
docker inspect 镜像[:tag]
指令语法
FROM
- 基于哪个镜像进行构建新的镜像,构建时都会自动从docker hub拉取base镜像作为Dockerfile的第一个指令出现
FROM <image>
FROM <image>[:<tag>] 使用版本不写为latest
RUN
- RUN指令将在当前映像之上的新层中执行任何命令并提交结果。生成的提交映像将用于Dockerfile中的下一步
- 语法:
RUN <command> (shell form, the command is run in a shell, which by default is /bin/sh -c on Linux or cmd /S /C on Windows)
RUN echo hello
RUN ["executable","param1","param2"](exec form)
RUN ["/bin/bash","-c","echo hello"] # 指定bash执行命令
RUN yum install vim
RUN ["yum","install","vim"]
EXPOSE (重要:外部与容器通信的通道)
- 用来指定构建的镜像在运行为容器时对外暴露的端口
EXPOSE 80/tcp # 不则默认使用tcp
EXPOSE 80/udp
CMD
- 用来为启动的容器指定执行的命令,
注意:在Dockerfile中只能有一条CMD指令。如果列出多个命令,则只有最后一个命令才会生效。
CMD ["executable","param1","param2"](exec form, this is the preferred form)
CMD ["param1","param2"](as default parameters to ENTRYPOINT)
CMD command param1 param2(shell form)
WORKDIR
- 用来为Dockerfile中的任何RUN、CMD、ENTRYPOINT、COPY和ADD指令设置工作目录。如果WORKDIR不存在,即使它没有在任何后续Dockerfile指令中使用,它也将被创建。
WORKDIR /path/to/workdir
WORKDIR /a
WORKDIR b
WORKDIR C
# 注意:WORKDIR指令可以在Dockerfile中多次使用。如果提供了相对路径,则该路径将与先前WORKDIR指令的路径相对
ENV
- 用来为构建镜像设置环境变量。这个值将出现在构建阶段中所有后续指令的环境中。
ENV <key> <value>
ADD (支持通配符)
- 用来从context上下文复制新文件、目录或远程文件url,并将它们添加到位于指定路径的映像文件系统中。
ADD hom* /mydir/ # 通配符添加多个文件
ADD hom?.txt /mydir/ # 通配符添加
ADD test.txt relativeDir/ # 可以指定相对路径
ADD test.txt /absoluteDir/ # 也可以指定绝对路径
ADD url
COPY命令
- 用来将context目录中指定文件复制到镜像的指定目录中
COPY src dest
COPY ["<src>", ... "<dest>"]
VOLUME命令
- 用来定义容器运行时可以挂在到宿主机的目录,如果构建的时候没写,则不允许任何容器内数据被挂载
VOLUME ["/data"]
Dockerfile构建springboot项目部署
-
找一个能正常运行的springboot项目,使用maven的打包工具达成jar包
-
将可运行的jar包上传到服务器中
-
在Dockerfile中构建jar包的运行环境
-
在服务器中编写Dockerfile
-
FROM openjdk:8 WORKDIR /jar_run ADD test.jar /jar_run EXPOSE 8989 ENTRYPOINT ["java","-jar"] CMD ["test.jar"]
-
-
构建镜像
- docker build 名称[:tag] .
-
运行镜像
- docker run -d -p 8989:8989 --name test test:lastes
- 注意:原项目中数据库连接地址url由localhost变更为指定路径,容器与容器之间是隔离的,使用localhost访问不到彼此之间的容器。
- 解决方案:可以尝试把mysql构建在springboot程序运行环境中一同构建成为自定义镜像,避免更改所有数据库连接地址
-
访问项目
查看docker容器IP
参考:https://blog.csdn.net/web18224617243/article/details/126327598
- docker
# 获取某个容器ip
docker -it 容器 cat /etc/hosts
docket inspect 容器
docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' 容器
# 获取所有容器ip
docker inspect -f '{{.Name}} - {{.NetworkSettings.IPAddress }}' $(docker ps -aq)
- 使用
docker-compose
获取容器ip
docker inspect -f '{{.Name}} - {{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' $(docker ps -aq)
docker inspect --format='{{.Name}} - {{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' $(docker ps -aq)
- 用户脚本
经验:可以考虑在 ~/.bashrc 中写一个 bash 函数:
cd && vim .bashrc
docker_ip() {
sudo docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' $1
}
dockeriplist() {
sudo docker inspect -f '{{.Name}} - {{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' $(docker ps -aq)
}
source .bashrc
测试脚本
# 查看指定容器ip
docker_ip <容器>
# 查看所有容器ip
dockeriplist
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
· 一个奇形怪状的面试题:Bean中的CHM要不要加volatile?
· 分享4款.NET开源、免费、实用的商城系统
· Obsidian + DeepSeek:免费 AI 助力你的知识管理,让你的笔记飞起来!
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了