目录
2.4 提前在本地创建软件包索引缓存,以此来提高搜索和安装软件的速度
3.3 配置加速器【https://cr.console.aliyun.com/cn-hangzhou/instances/mirrors】
docker exec -it 运行容器的名称 ping 宿主机ip ap01 172.17.0.2 ap02 172.17.0.3
2.1 默认情况下,docker容器之间都是通过IP互连的,但是容器IP会改变(重启,停止等操作)
2.3 基于安全考虑,可以通过 vim /etc/docker/daemon.json 在末尾添加配置【阻断容器之间的默认连通(所有容器之间都不能互通)】
4、自定义网络【将不同的容器加入到同一个自定义网络中,可以实现容器之间自动开启别名互连】
五、Docker 容器部署项目(Mysql数据库、Java、nginx服务)
2.4 运行容器【命令两种展示方式,命令一样,但是偶尔会出现方法一运行后立即停止的情况,可以使用命令二】
3.4 运行容器【命令两种展示方式,命令一样,但是偶尔会出现方法一运行后立即停止的情况,可以使用命令二】
2.1 安装 Docker 引擎时附带 docker-compose 插件
4.1 创建目录用于存放 docker-compose 的配置
4.2 创建并编写 docker-compose.yml 文件【文件为 json 格式】
(文章来自一个前端开发的研究,代码(命令)是经过反复测试的,理论知识是自己浅薄的认知(也有借鉴其他文章),共同学习)
一、docker 是什么?
docker是一个用来装应用的容器,就像杯子可以装水,笔筒可以放笔,书包可以放书,可以把hello word放在docker中,可以把网站放入docker中,可以把任何想得到的程序放在docker中。
二、为什么要用 docker ?
1、 系统环境不一致
本地开发正常,服务器正常,但是测试环境(或者其他环境)出问题
docker把操作系统,jdk,tomcat,代码,配置全部放到集装箱里.再打包放到鲸鱼上,由鲸鱼给我们送到服务器上,在开发人员的机器上怎么运行,在别的机器上也怎么运行.不会有任何的问题.一句话就是docker解决了运行环境不一致所带来的问题。
2、 隔离性
docker 是沙箱逻辑,每个系统的配置都是独立的,互相之间不受影响
三、Linux 系统安装docker容器
注:如果报错 “/var/run/yum.pid 已被锁定,PID 为 10853 的另一个程序正在运行。”
原因是上次使用yum命令之后还没有结束进程。每个进程启动之后都会默认在/var/run目录生产pid文件。删除掉就可以继续使用了。
# 删除yum.pid文件
rm -rf /var/run/yum.pid
1、 卸载旧版(可选)
1.1 停止 docker 服务
systemctl stop docker
1.2 查看已经安装的docker软件包
yum list installed | grep docker
1.3 卸载已经安装的docker软件包
# 以 docker* 开头
# -y 避免后面重复确认
yum remove containerd.io.x86_64 docker* -y
1.4 删除 Docker 数据和配置文件
# 存放容器)镜像)网络)卷的配置
rm -rf /var/lib/docker
# 管理 Docker 容器生命周期的组件(Docker容器的运行环境)
rm -rf /var/lib/containerd
# docker 的配置文件
rm -rf /etc/docker
2、安装准备
2.1 查看系统版本
cat /etc/centos-release
2.2 查看系统版本内核
uname -a
2.3 设置docker镜像源
yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
sed -i 's+download.docker.com+mirrors.aliyun.com/docker-ce+' /etc/yum.repos.d/docker-ce.repo
2.4 提前在本地创建软件包索引缓存,以此来提高搜索和安装软件的速度
yum makecache fast
2.5 yum 包更新到最新
yum update
2.6 安装指定工具包
yum install -y yum-utils device-mapper-persistent-data lvm2
3、 安装docker社区版
3.1 安装命令
# ce为免费的社区版
# docker-ce-cli 是Docker Engine 的命令行界面
# containerd.io 是容器运行的基本组件,负责管理容器的生命周期
yum install -y docker-ce docker-ce-cli containerd.io docker~build-plugin docker-compose-plugin
3.2 centos7 启动 docker 服务
关闭防火墙
systemctl stop firewalld
禁止防火墙开机自启动
systemctl disable firewalld
启动docker
systemctl start docker
查询当前状态
systemctl status docker
运行时的状态:
停止的状态:
3.3 配置加速器【https://cr.console.aliyun.com/cn-hangzhou/instances/mirrors】
网址进入阿里云的控制台,找到“镜像加速器”=>"CengOS"复制配置项
sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": ["https://6vfewj39.mirror.aliyuncs.com"]
}
EOF
sudo systemctl daemon-reload
sudo systemctl restart docker
3.4 设置开机自启
systemctl enable docker
systemctl start docker
4、 测试安装
查看版本号(可以查看是否安装了docker 容器)
docker -v
查看 docker-compose 版本
docker compose version
拉取镜像
docker pull hello-world
启动容器
docker run hello-world
输出 Hello from Docker! 说明成功
5、常用命令
拉取镜像:
docker pull 镜像名称:版本
如果不指定版本,则拉取最新版本
运行镜像:
docker run -itd --name 运行的名称 镜像名称
# --link 运行的名称:镜像别名(可以直接修改镜像的hosts映射)(/etc/hosts)
docker run -itd --name 运行的名称 --link 运行的名称:镜像别名 镜像名称
查看运行的容器:
docker ps
查看历史运行容器:
docker ps -a
停止容器运行:
docker stop 运行的名称
删除容器(如果镜像名称有且只有一个,就可以使用ID删除,如果有多个,就要使用"镜像名称:版本号"进行删除)
docker rmi -f 镜像ID/镜像名称 rmi 镜像名称/镜像名称:版本号
删除历史容器(运行中/已停止)
docker rm 容器名称
删除已经停止的容器
docker container prune
进入运行容器执行命令
docker exec -it 运行的名称
查看运行容器ip地址
docker exec -it 运行的名称 hostname -i
进入运行容器查看内部数据:
docker exec -it 运行的名称 bash
进入容器内部后退出
exit
# 查看本地镜像
docker images
表头说明:
REPOSITORY:镜像名称
TAG:镜像版本 latest指最新版
IMAGE ID:镜像ID(删除时会用到)
CREATED:创建时间
SIZE:镜像大小
# 搜索镜像(docker search 镜像名称)(自动到 docker hub 上查询)
docker search nginx
(搜索展示的结果没有版本号,想要下载具体的版本,到docker hub 上查询具体版本)
表头说明:
NAME:镜像名称
DESCRIPTION:描述信息
STARS:点赞数
OFFICIAL:是否为官方团队维护
# 拉取镜像(没有版本号默认拉取最新版)
docker pull nginx
# 删除镜像(如果镜像名称有且只有一个,就可以使用ID删除,如果有多个,就要使用"镜像名称:版本号"进行删除)
docker rmi 镜像ID / docker rmi 镜像名称:版本号
# 查看所有的镜像列表
docker images -q
# 删除所有镜像(轻易不要用)
docker rmi `docker images -q`
6、 开机报错解决
6.1 报错:
报错:Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?
原因:docker容器没有启动
解决:运行命令启动 docker
systemctl start docker
四、Docker 网络
1、 容器与宿主机互连
docker exec -it 运行容器的名称 ping 宿主机ip
ap01 172.17.0.2
ap02 172.17.0.3
2、 容器与容器互连
2.1 默认情况下,docker容器之间都是通过IP互连的,但是容器IP会改变(重启,停止等操作)
2.2 通过容器别名进行连接
# --link 运行的名称:镜像别名(可以直接修改镜像的hosts映射)(/etc/hosts)
docker run -itd --name 运行的名称 --link 运行的名称:镜像别名 镜像名称
2.3 基于安全考虑,可以通过 vim /etc/docker/daemon.json 在末尾添加配置【阻断容器之间的默认连通(所有容器之间都不能互通)】
"icc": false
可禁止容器之间的互连,但是可以通过 -- link 方式进行互连,并且不受 icc 方法影响(需要重启生效)
"iptables": true
systemctl restart docker
nginx01 172.17.0.2
nginx02 172.17.0.3
3、容器与外部相连
docker exec -it ap01 sh
ping www.baidu.com
4、自定义网络【将不同的容器加入到同一个自定义网络中,可以实现容器之间自动开启别名互连】
4.1 查看自定义网络
docker network ls
4.2 查看使用本网络的详情
docker network inspect 自定义网络名
4.3 创建自定义网络
# --derver:驱动类型,默认 bridge
# --subnet=192.168.1.0/24:网段设置,默认docker0地址向上递增【172.17.0.1-->172.18.0.0】
docker network create [--derver] [--subnet=192.168.1.0/24] 自定义网络名
通过以下命令查询更多参数说明
docker network create --help
4.4 使用自定义网络
容器启动时:
docker run --network 自定义网络名 ...
容器启动后:
docker network connect 网络名 容器名
4.5 删除自定义网络【必须确保网络未被使用过】
docker network rm 网络名
将容器退出自定义网络
docker network disconnect 网络名 容器名
5、端口映射
5.1 运行时指定端口
docker run -itd --name 运行的名称 -p 外部访问端口:容器内部端口 镜像名称
5.2 修改端口映射
5.2.1 停止 docker 服务
# 停止后不能进行任何操作,否则会自动重启服务
systemctl stop docker
5.2.2 修改“hostconfig.json”
查询容器ID
docker ps
cd /var/lib/docker/containers
cd 容器ID(输入前几位,然后按tab键自动补齐)
vim hostconfig.json
搜索"PortBindings"【进入文件,直接输入/粘贴关键字回车就可以搜索】
# "HostIp":"如果为空,代表容器内部可以使用任意端口进行访问"
# "HostPort":"宿主机端口设置"
"PortBindings":{"80/tcp":[{"HostIp":"","HostPort":"81"}]}
5.2.3 重启docker及服务
systemctl start docker
docker start 镜像运行的名称
5.3 查看镜像端口映射
docker port 运行的名称
docker ps -a 也可以查看,在返回信息的表头 PORTS 字段显示
5.4 防火墙问题
5.4.1 开放指定端口
添加指定端口
firewalld-cmd --zone=public --permanent --add-port=80/tcp
重启防火墙
firewalld-cmd --reload
5.4.2 停止并禁用防火墙【不安全】
停止防火墙
systemctl stop firewalld
禁止开机自启
systemctl disable firewalld
五、Docker 容器部署项目(Mysql数据库、Java、nginx服务)
1、创建专用网络【方便容器之间使用别名进行连接】
docker network create appnet
2、构建 mysql 服务器镜像
2.1 准备工作
拉取镜像
docker pull mysql:8.0
创建专用目录
mkdir app/db -p
获取配置文件
【下方所有操作(构建脚本、运行容器)都在该目录下完成】
cd app/db
# 运行一个临时容器,要使用里面的配置文件
docker run --name temp -itd -e MYSQL_ROOT_PASSWORD=123456 mysql
# 复制主配置文件
docker cp temp:/etc/mysql/my.cnf .
# 复制从配置文件
docker cp temp:/etc/mysql/conf.d .
# 删除临时容器
docker rm -f temp
修改字符集
vim my.cnf
[mysql]
default-character-set=utf8mb4
[mysql.server]
default-character-set=utf8mb4
准备初始化脚本init.sql
2.2 构建脚本【Dockerfile文件】
# 指定基础镜像
FROM mysql:latest
# 拷贝数据库初始化脚本到指定目录
COPY init.sql /docker-entrypoint-initdb.d
2.3 执行构建
docker build -t myappdb .
2.4 运行容器【命令两种展示方式,命令一样,但是偶尔会出现方法一运行后立即停止的情况,可以使用命令二】
方法一:
docker run --name appDB -itd \
-p 3306:3306 \
-v ./my.cnf:/etc/mysql/my.cnf \
-v ./conf.d:/etc/mysql/conf.d \
-v ./data:/var/lib/mysql \
-e MYSQL_ROOT_PASSWORD=123456 \
--network appnet \
myappdb
方法二:
docker run --name appDB -itd -p 3306:3306 -v ./my.cnf:/etc/mysql/my.cnf -v ./my.cnf:/etc/mysql/my.cnf -v ./conf.d:/etc/mysql/conf.d -v ./data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 --network appnet myappdb
3.构建后端服务器镜像
3.1 准备工作
创建专用目录
mkdir app/javaBuild -p
创建后端配置文件
【下方所有操作(构建脚本、运行容器)都在该目录下完成】
cd app/javaBuild
【通过配置文件修改数据库连接信息(账号、密码等),该文件优先级高于项目代理的配置】
vim application.properties
spring.datasource.url=jdbc:mysql://appDB:3306/sql01
spring.datasource.username=root
spring.datasource.password=123456
后端文件打包
idea -> maven -> clean && package -> myapp.jar
3.2 构建脚本【Dockerfile】
# 指定基础镜像(因 SpringBoot3 要求jdk17+)
FROM openjdk:11.0
# 工作目录app
WORKDIR /app
# 拷贝jar包
COPY myapp.jar .
# 暴露后端
EXPOSE 8088
# 默认执行jar
CMD ["java","-jar","myapp.jar"]
3.3 执行构建
# javaBuild:镜像名
docker build -t javabuild .
3.4 运行容器【命令两种展示方式,命令一样,但是偶尔会出现方法一运行后立即停止的情况,可以使用命令二】
# appBackend:容器名
# 8899:8899 宿主机端口:容器端口
# appnet 自定义的网络名
# javaBuild:镜像名
方法一:
docker run --name appServer -itd \
-p 8899:8899 \
-v ./application.yml:/app/application.yml \
--network appnet \
javaBuild
方法二:
docker run --name appServer -itd -p 8088:8088 -v ./application.properties:/app/application.properties --network appnet javabuild
4、部署nginx服务(前端)
4.1 准备工作
创建专用目录
mkdir app/nginx/html -p
获取配置文件(启动一个临时的容器,将里面的配置文件复制出来)
【后续操作(从获取配置文件一直到启动容器)都在该目录下进行】
cd app/nginx
# 启动临时的容器
docker run --name temp -itd nginx
# 复制主配置文件
docker cp temp:/etc/nginx/nginx.conf ./nginx.conf
# 复制从配置文件
docker cp temp:/etc/nginx/conf.d .
# 删除临时文件
docker rm -f temp
修改配置文件
vim ./conf.d/default.conf
server{
location / {
root /usr/share/nginx/html;
index index.html index.htm;
try_files $uri /index.html;
}
location /api/ {
rewrite ^.+api/?(.*)$ /$1 break;
proxy_pass http://appServer:8088;
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
4.2 构建脚本【Dockerfile 文件】
# 指定基础镜像(nginx)
FROM nginx:latest
# 拷贝前端文件
COPY ./html /usr/share/nginx/html
# 暴露前端宿主机端口8082
EXPOSE 8082
4.3 执行构建
# nginxBuild:镜像的名字
docker build -t nginxbuild .
4.4 运行容器
# nginx_demo 容器的名字
# -p 8082:80 宿主机端口:容器端口
# --network appnet 加入网络(便于访问) appnet:自定义的网络名
# nginxbuild 镜像名
docker run --name nginx_demo -itd -p 8082:80 -v ./nginx.conf:/etc/nginx/nginx.conf -v ./conf.d:/etc/nginx/conf.d --network appnet nginxbuild
六、Docker compose 编排技术
1、为什么使用 Docker compose 编排技术?
使用该技术管理容器,可以简化到使用一条命令迅速启动内部管理的容器
mysql、java、nginx这几个容器启动需要经历 docker build 和 docker run 命令,三个容器就要执行六次命令,使用 docker compose 管理,一条命令就可以启动三个容器
2、安装
2.1 安装 Docker 引擎时附带 docker-compose 插件
yum install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
或者安装 Docker 引擎后补充安装 docker-compose 插件
yum install -y docker-compose-plugin
3、测试安装结果
docker compose version
4、配置所需文件
4.1 创建目录用于存放 docker-compose 的配置
mkdir myprj
【后续编辑配置文件和运行项目都在该目录下】
cd myprj
4.2 创建并编写 docker-compose.yml 文件【文件为 json 格式】
# 版本信息可以查看网站:https://docs.docker.com/compose/compose-file/compose-versioning/ 找到对应的 docker 版本
version: "3.8"
# 应用程序使用的名字(不指定该属性,则默认使用 yml 文件所在目录名)
# 只能包含小写字母,数字、破折号和下划线,且必须以小写字母或数字开头
name: "myapp"
# 定义应用程序所需的服务集合
services:
# 自定义的服务名
appnginx:
# 打包所需的文件
build: ./nginx
# 端口映射
ports:
# 宿主机端口:容器端口
- "80:80"
# 挂载的文件
volumes:
- ./nginx/nginx.conf:/etc/nginx/nginx.conf
- ./nginx/conf.d:/etc/nginx/conf.d
# 定义应用程序使用的网络(网络不存在会自动创建)
networks:
- net1
# 依赖的服务
depends_on:
- appbackend
appbackend:
build: ./javaBuild
ports:
- "8088:8088"
volumes:
- ./javaBuild/application.properties:/app/application.properties
networks:
- net1
depends_on:
- appdb
appdb:
build: ./db
ports:
- "3306:3306"
volumes:
- ./db/conf.d:/etc/mysql/conf.d
- ./db/data:/var/lib/mysql
- ./db/my.cnf:/etc/mysql/my.cnf
networks:
- net1
# 环境的配置,通常将数据库名及密码加入其中
# 文件前面加 . 表示该文件在Linux系统中是隐藏的
env_file:
- .mysql_env
# 暴露的端口号
expose:
- "3306"
# 自定义的网络
networks:
net1:
driver: bridge # 默认 bridge 网络模式(可以省略不写)
5、docker-compose 常用命令
5.1 docker compose config
含义:验证和显示由 docker-compose.yml 文件定义的服务配置5.2 docker compose up [-d]
含义:启动应用程序所需的所有服务。
-d 代表后台运行5.3 docker compose ps
含义:查看已经启动的容器5.4 docker compose stop/kill [容器名]
含义:停止已经启动的容器。
kill:强制停止容器。
后面加上容器名,代表只停止指定的容器5.5 docker compose start/restart [容器名]
含义:启动被停止的容器(重启容器)5.6 docker compose exec 容器名 bash
含义:进入容器5.7 docker compose logs [-f]
含义:查看服务日志
-f 代表输出实时日志5.8 docker compose down
含义:用于停止和移除由 docker compose up 创建的容器、网络和卷
七、使用 Docker 容器部署项目,常见问题处理
1、可能会出现宿主机时间(或者容器时间)与系统时间不一样的情况
1.1 描述:
场景:
后端返回的数据中,时间字段与系统时间相差8小时的情况
原因:我们电脑系统使用的是东八区时间(上海),linux 系统使用的是
1.2 解决:
先查看宿主机的系统时间:
date
# 输出:Sun Jun 30 01:13:33 CST 2024
# 说明系统时间已经是需要的东八区时间,接下来进入容器查看容器时间
启动docker服务(我是通过 docker compose 统一管理项目的)
docker compose up -d
查看容器id
docker compose ps
进入对应容器(为了查询容器时间)
docker exec -it 容器id(或者名称) bash
查询容器时间
date
# 如果容器时间比系统时间晚8小时,说明没有同步
Sat Jun 29 16:53:57 UTC 2024
复制宿主机下面的zoneinfo文件到容器内
docker cp /usr/share/zoneinfo 容器id:/usr/share/
进入对应容器(为了解决时间)
docker exec -it 容器名 bash
ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
echo "Asia/Shanghai" > /etc/timezone
再次查询就会同步了
date
重启 docker 容器