第15章 项目部署-Docker
Docker技术能够避免部署对服务器环境的依赖,减少复杂的部署流程。
轻松部署各种常见软件、Java项目
参考文档:第十五章:项目部署(Docker) - 飞书云文档
15.1 Docker安装
15.1.1 卸载旧版
首先如果系统中已经存在旧的Docker,则先卸载:
yum remove docker \ docker-client \ docker-client-latest \ docker-common \ docker-latest \ docker-latest-logrotate \ docker-logrotate \ docker-engine \ docker-selinux
15.1.2 配置Docker的yum库
首先要安装一个yum工具
sudo yum install -y yum-utils device-mapper-persistent-data lvm2
安装成功后,执行命令,配置Docker的yum源(已更新为阿里云源):
sudo yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo sudo sed -i 's+download.docker.com+mirrors.aliyun.com/docker-ce+' /etc/yum.repos.d/docker-ce.repo
更新yum,建立缓存
sudo yum makecache fast
15.1.3 安装Docker
最后,执行命令,安装Docker
yum install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
15.1.4 启动和校验
# 启动Docker systemctl start docker # 停止Docker systemctl stop docker # 重启 systemctl restart docker # 设置开机自启 systemctl enable docker # 执行docker ps命令,如果不报错,说明安装启动成功 docker ps
15.1.5 配置镜像加速
镜像地址可能会变更,如果失效可以百度找最新的docker镜像。
配置镜像步骤如下:
# 创建目录 rm -f /etc/docker/daemon.json # 复制内容 tee /etc/docker/daemon.json <<-'EOF' { "registry-mirrors": [ "http://hub-mirror.c.163.com", "https://mirrors.tuna.tsinghua.edu.cn", "http://mirrors.sohu.com", "https://ustc-edu-cn.mirror.aliyuncs.com", "https://ccr.ccs.tencentyun.com", "https://docker.m.daocloud.io", "https://docker.awsl9527.cn" ] } EOF # 重新加载配置 systemctl daemon-reload # 重启Docker systemctl restart docker
15.2 部署-MySQL
传统方式部署MySQL,大概的步骤有:
搜索并下载MySQL安装包
上传至Linux环境
解压和配置环境
安装
初始化和配置
而使用Docker安装,仅仅需要一步即可,在命令行输入下面的命令(建议采用CV大法):
docker run -d \ --name mysql \ -p 3307:3306 \ -e TZ=Asia/Shanghai \ -e MYSQL_ROOT_PASSWORD=123 \ mysql:8
如果没有 mysql:8 镜像会先下载镜像image,再部署这个取名叫mysql的容器container
因此,Docker安装软件的过程,就是自动搜索下载镜像,然后创建并运行容器的过程。
运行效果如图(在给大家提供的资料中,已经下载好了mysql 8版本的镜像):
MySQL安装完毕!通过任意客户端工具即可连接到MySQL。
15.3 docker命令解析
docker run
运行流程如下:
Docker镜像交流的社区:https://hub.docker.com
利用Docker快速的安装了MySQL,非常的方便,不过我们执行的命令到底是什么意思呢?
docker run -d \ --name mysql \ -p 3307:3306 \ -e TZ=Asia/Shanghai \ -e MYSQL_ROOT_PASSWORD=123 \ mysql:8
解读:
docker run -d
:创建并运行一个容器,-d
则是让容器以后台进程运行--name mysql
: 给容器起个名字叫mysql
,你可以叫别的-p 3307:3306
: 设置端口映射。容器是隔离环境,外界不可访问。但是可以将宿主机端口映射容器内到端口,当访问宿主机指定端口时,就是在访问容器内的端口了。
容器内端口往往是由容器内的进程决定,例如MySQL进程默认端口是3306,因此容器内端口一定是3306;而宿主机端口则可以任意指定,一般与容器内保持一致。
格式:
-p 宿主机端口:容器内端口
,示例中就是将宿主机的3307映射到容器内的3306端口
-e TZ=Asia/Shanghai
: 配置容器内进程运行时的一些参数格式:
-e KEY=VALUE
,KEY和VALUE都由容器内进程决定案例中,
TZ=Asia/Shanghai
是设置时区;MYSQL_ROOT_PASSWORD=123
是设置MySQL默认密码
mysql:8
: 设置镜像名称,Docker会根据这个名字搜索并下载镜像格式:
REPOSITORY:TAG
,例如mysql:8.0
,其中REPOSITORY
可以理解为镜像名,TAG
是版本号在未指定
TAG
的情况下,默认是最新版本,也就是mysql:latest
15.4 docker常见命令
常见的命令有:
命令 | 说明 | 文档地址 |
---|---|---|
docker pull | 拉取镜像 | docker pull |
docker push | 推送镜像 | docker push |
docker images | 查看本地镜像 | docker images |
docker rmi | 删除本地镜像 | docker rmi |
docker run | 创建并运行容器 | docker run |
docker stop | 停止指定容器 | docker stop |
docker start | 启动指定容器 | docker start |
docker restart | 重新启动容器 | docker restart |
docker rm | 删除指定容器 | docs.docker.com |
docker ps [-a] | 查看容器 | docker ps |
docker logs | 查看容器运行日志 | docker logs |
docker exec -it [containerName] bash | 进入容器 | docker exec |
docker save | 保存镜像到本地压缩文件 | docker save |
docker load | 加载本地压缩文件到镜像 | docker load |
docker inspect | 查看容器详细信息 | docker inspect |
用一副图来表示这些命令的关系:
补充:
默认情况下,每次重启虚拟机我们都需要手动启动Docker和Docker中的容器。通过命令可以实现开机自启:
# Docker开机自启 systemctl enable docker # Docker容器开机自启 docker update --restart=always [容器名/容器id]
用Nginx为例给大家演示命令。
# 第1步,去DockerHub查看nginx镜像仓库及相关信息 # 第2步,拉取Nginx镜像 (比较耗时) docker pull nginx:1.20.2 # 第3步,查看镜像 docker images # 第4步,创建并允许Nginx容器 docker run -d --name nginx -p 80:80 nginx # 第5步,查看运行中容器 docker ps # 也可以加格式化方式访问,格式会更加清爽 docker ps --format "table {{.ID}}\t{{.Image}}\t{{.Ports}}\t{{.Status}}\t{{.Names}}" # 第6步,访问网页,地址:http://虚拟机地址 # 第7步,停止容器 docker stop nginx # 第8步,查看所有容器 docker ps -a --format "table {{.ID}}\t{{.Image}}\t{{.Ports}}\t{{.Status}}\t{{.Names}}" # 第9步,再次启动nginx容器 docker start nginx # 第10步,再次查看容器 docker ps --format "table {{.ID}}\t{{.Image}}\t{{.Ports}}\t{{.Status}}\t{{.Names}}" # 第11步,查看容器详细信息 docker inspect nginx # 第12步,进入容器,查看容器内目录 docker exec -it nginx bash # 或者,可以进入MySQL docker exec -it mysql mysql -uroot -p # 第13步,删除容器 docker rm nginx # 发现无法删除,因为容器运行中,强制删除容器 docker rm -f nginx
15.5 数据卷
数据卷(volume)是一个虚拟目录,是容器内目录与宿主机目录之间映射的桥梁。
以Nginx为例,我们知道Nginx中有两个关键的目录:
html
:放置一些静态资源conf
:放置配置文件
我们可以配置这两个关键目录的数据卷。
数据卷的相关命令有:
命令 | 说明 | 文档地址 |
---|---|---|
docker volume create | 创建数据卷 | docker volume create |
docker volume ls | 查看所有数据卷 | docs.docker.com |
docker volume rm | 删除指定数据卷 | docs.docker.com |
docker volume inspect | 查看某个数据卷的详情 | docs.docker.com |
docker volume prune | 清除数据卷 | docker volume prune |
注意:容器与数据卷的挂载要在创建容器时配置,对于创建好的容器,是不能设置数据卷的。而且创建容器的过程中,数据卷会自动创建。
教学演示环节:演示一下nginx的html目录挂载
# 1.首先创建容器并指定数据卷,注意通过 -v 参数来指定数据卷 docker run -d --name nginx -p 80:80 -v html:/usr/share/nginx/html nginx:1.20.2 # 2.然后查看数据卷 docker volume ls # 3.查看数据卷详情 docker volume inspect html # 4.查看/var/lib/docker/volumes/html/_data目录 ll /var/lib/docker/volumes/html/_data # 5.进入该目录,并随意修改index.html内容 cd /var/lib/docker/volumes/html/_data vi index.html # 6.打开页面,查看效果 # 7.进入容器内部,查看/usr/share/nginx/html目录内的文件是否变化 docker exec -it nginx bash
数据卷的默认目录是比较深的,在更多情况下,我们会直接将容器目录与宿主机指定目录挂载。
-v mysql:/var/lib/mysql # 会被识别为一个数据卷叫mysql,运行时会自动创建这个数据卷 -v ./mysql:/var/lib/mysql # 会被识别为当前目录下的mysql目录,运行时如果不存在会创建目录注意:本地目录或文件必须以
/
或./
开头,如果直接以名字开头,会被识别为数据卷名而非本地目录名。
15.6 自定义镜像
镜像中包含了程序运行需要的系统函数库、环境、配置、依赖。
因此,自定义镜像本质就是依次准备好程序运行的基础环境、依赖、应用本身、运行配置等文件,并且打包而成。
所以镜像就是一堆文件的集合。
15.6.1 Dockerfile
Dockerfile记录了镜像结构。
常用的指令:
指令 | 说明 | 示例 |
---|---|---|
FROM | 指定基础镜像 | FROM centos:7 |
ENV | 设置环境变量,可在后面指令使用 | ENV key value |
COPY | 拷贝本地文件到镜像的指定目录 | COPY ./xx.jar /tmp/app.jar |
RUN | 执行Linux的shell命令,一般是安装过程的命令 | RUN yum install gcc |
EXPOSE | 指定容器运行时监听的端口,是给镜像使用者看的 | EXPOSE 8080 |
ENTRYPOINT | 镜像中应用的启动命令,容器运行时调用 | ENTRYPOINT java -jar xx.jar |
例如,要基于 centos:7 镜像来构建一个Java应用,其Dockerfile内容如下:
# 使用 CentOS 7 作为基础镜像 FROM centos:7 # 添加 JDK 到镜像中 COPY jdk17.tar.gz /usr/local/ RUN tar -xzf /usr/local/jdk17.tar.gz -C /usr/local/ && rm /usr/local/jdk17.tar.gz # 设置环境变量 ENV JAVA_HOME=/usr/local/jdk-17.0.10 ENV PATH=$JAVA_HOME/bin:$PATH # 创建应用目录 RUN mkdir -p /app WORKDIR /app # 复制应用 JAR 文件到容器 COPY app.jar app.jar # 暴露端口 EXPOSE 8080 # 运行命令 ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app/app.jar"]
Dockerfile文件编写好了之后,就可以使用如下命令来构建镜像了。
docker build -t 镜像名 .
-t :是给镜像起名,格式依然是repository:tag的格式,不指定tag时,默认为latest
. :是指定Dockerfile所在目录,如果就在当前目录,则指定为"."
15.7 docker网络
每一个容器再被创建出来都会被分配一个虚拟的IP地址,可以通过命令查看:
# 1.用基本命令,寻找Networks.bridge.IPAddress属性 docker inspect mysql # 也可以使用format过滤结果 docker inspect --format='{{range .NetworkSettings.Networks}}{{println .IPAddress}}{{end}}' mysql
容器网络相关的常见命令有:
命令 | 说明 |
---|---|
docker network create | 创建一个网络 |
docker network ls | 查看所有网络 |
docker network rm | 删除指定网络 |
docker network prune | 清除未使用的网络 |
docker network connect | 使指定容器连接加入某网络 |
docker network disconnect | 使指定容器连接离开某网络 |
docker network inspect | 查看网络详细信息 |
教学演示:自定义网络
# 1.首先通过命令创建一个网络 docker network create itheima # 2.然后查看网络 docker network ls # 结果: NETWORK ID NAME DRIVER SCOPE 639bc44d0a87 bridge bridge local 403f16ec62a2 itheima bridge local 0dc0f72a0fbb host host local cd8d3e8df47b none null local # 其中,除了itheima以外,其它都是默认的网络 # 3.让 myapp 和 mysql 都加入该网络 # 3.1.mysql容器,加入 itheima 网络 docker network connect itheima mysql # 3.2.myapp容器,也就是我们的java项目, 加入 itheima 网络 docker network connect itheima myapp # 4.进入dd容器,尝试利用别名访问db # 4.1.进入容器 docker exec -it myapp bash # 4.2.用容器名访问 ping mysql # 结果: PING mysql (172.18.0.2) 56(84) bytes of data. 64 bytes from mysql.itheima (172.18.0.2): icmp_seq=1 ttl=64 time=0.044 ms 64 bytes from mysql.itheima (172.18.0.2): icmp_seq=2 ttl=64 time=0.054 ms
也可以在docker run时用--network参数配置该容器的虚拟网络。
15.8 部署-Java项目
需求:将我们开发的 tlias-web-management 项目打包为镜像,并部署。
步骤:
修改项目的配置文件,修改数据库服务地址(打包package)。
在logback.xml中修改lombok日志文件的文件输出路径
在application.properties文件中修改数据库信息
编写Dockerfile文件(AI辅助)。
Dockerfile(文件名):
# 使用 CentOS 7 作为基础镜像 FROM centos:7 # 添加 JDK 到镜像中 COPY jdk17.tar.gz /usr/local/ RUN tar -xzf /usr/local/jdk17.tar.gz -C /usr/local/ && rm /usr/local/jdk17.tar.gz # 设置环境变量 ENV JAVA_HOME=/usr/local/jdk-17.0.10 ENV PATH=$JAVA_HOME/bin:$PATH # 阿里云OSS环境变量 ENV OSS_ACCESS_KEY_ID=LTAI5tP6dc4cvccdvvySE39X ENV OSS_ACCESS_KEY_SECRET=ZSyIT31qhxIkS0dH1H9WzHqPiyM3Ot #统一编码 ENV LANG=en_US.UTF-8 ENV LANGUAGE=en_US:en ENV LC_ALL=en_US.UTF-8 # 创建应用目录 RUN mkdir -p /tlias WORKDIR /tlias # 复制应用 JAR 文件到容器 COPY tlias.jar tlias.jar # 暴露端口 EXPOSE 8080 # 运行命令 ENTRYPOINT ["java","-jar","/tlias/tlias.jar"]
构建Docker镜像,部署Docker容器,运行测试。
除了Dockerfile文件外。
依赖基础镜像Linux
依赖jdk镜像,将例如jdk17.tar.gz放到文件中。
构建Docker镜像
docker build -t tlias:1.0 .
部署Docker容器
docker run -d --name tlias-server --network itheima -p 8080:8080 tlias:1.0
通过 docker logs -f 容器名
,就可以查看容器的运行日志。
这样后端服务,就已经启动起来了。
15.9 部署-Nginx前端
需求:创建一个新的nginx容器,将资料中提供的前端项目的静态资源部署到nginx中。
步骤:
在宿主机上准备静态文件及配置文件存放目录(在
/usr/local
目录下创建tlias-web
目录)。-v /usr/local/tlias-web/html:/usr/share/nginx/html
-v /usr/local/tlias-web/conf/nginx.conf:/etc/nginx/nginx.conf
部署nginx容器
docker run -d \ --name nginx-tlias \ -v /usr/local/tlias-web/html:/usr/share/nginx/html \ -v /usr/local/tlias-web/conf/nginx.conf:/etc/nginx/nginx.conf \ --network itheima \ -p 80:80 \ nginx:1.20.2
15.10 DockerCompose自动部署
手动的逐一部署,太麻烦了。
而Docker Compose就可以帮助我们实现多个相互关联的Docker容器的快速部署。
用户通过一个单独的 docker-compose.yml 模板文件定义一组相关联的应用容器。
举例来说,用docker run部署MySQL的命令如下:
docker run -d \ --name nginx-tlias \ -p 80:80 \ -v /usr/local/app/html:/usr/share/nginx/html \ -v /usr/local/app/conf/nginx.conf:/etc/nginx/nginx.conf \ --network itheima \ nginx:1.20.2
如果用docker-compose.yml
文件来定义,就是这样:
services: mysql: image: "nginx:1.20.2" container_name: nginx-tlias ports: - "80:80" volumes: - "/usr/local/app/html:/usr/share/nginx/html" - "/usr/local/app/conf/nginx.conf:/etc/nginx/nginx.conf" networks: - itheima networks: itheima: name: itheima
对比如下:
docker run 参数 | docker compose 指令 | 说明 |
---|---|---|
--name | container_name | 容器名称 |
-p | ports | 端口映射 |
-e | environment | 环境变量 |
-v | volumes | 数据卷配置 |
--network | networks | 网络 |
明白了其中的对应关系,相信编写docker-compose
文件应该难不倒大家。
services: mysql: image: mysql:8 container_name: mysql ports: - "3307:3306" environment: TZ: Asia/Shanghai MYSQL_ROOT_PASSWORD: 123 volumes: - "/usr/local/app/mysql/conf:/etc/mysql/conf.d" - "/usr/local/app/mysql/data:/var/lib/mysql" - "/usr/local/app/mysql/init:/docker-entrypoint-initdb.d" networks: - tlias-net tlias: build: context: . dockerfile: Dockerfile container_name: tlias-server ports: - "8080:8080" networks: - tlias-net depends_on: - mysql nginx: image: nginx:1.20.2 container_name: nginx ports: - "80:80" volumes: - "/usr/local/app/nginx/conf/nginx.conf:/etc/nginx/nginx.conf" - "/usr/local/app/nginx/html:/usr/share/nginx/html" depends_on: - tlias networks: - tlias-net networks: tlias-net: name: itheima
编写好docker-compose.yml文件,就可以部署项目了。语法如下:
docker compose [OPTIONS] [COMMAND]
其中,OPTIONS和COMMAND都是可选参数,比较常见的有:
类型 | 参数或指令 | 说明 |
---|---|---|
Options | -f | 指定compose文件的路径和名称 |
-p | 指定project名称。project就是当前compose文件中设置的多个service的集合,是逻辑概念 | |
Commands | up | 创建并启动所有service容器 |
down | 停止并移除所有容器、网络 | |
ps | 列出所有启动的容器 | |
logs | 查看指定容器的日志 | |
stop | 停止容器 | |
start | 启动容器 | |
restart | 重启容器 | |
top | 查看运行的进程 | |
exec | 在指定的运行中容器中执行命令 |
例如:基于DockerCompose部署项目
docker compose up -d