【Docker】Docker 项目实战

👑4 项目实战

💫4.1 Docker Desktop on Windows

想要在开发环境能够结合 maven 自动化构建镜像,就需要先给你自己的电脑安装一个 Docker,目前 Docker 针对 Windows 和 Mac 平台都推出了 Desktop 桌面版本,直接按照官方文档安装即可。

官方文档:https://docs.docker.com/desktop/install/windows-install/

4.1.1 开启虚拟化服务

Hyper-V

如果服务中没有 Hyper-V,创建一个文本文件,保存下方内容

pushd "%~dp0"
dir /b %SystemRoot%\servicing\Packages\*Hyper-V*.mum >hyper-v.txt
for /f %%i in ('findstr /i . hyper-v.txt 2^>nul') do dism /online /norestart /add-package:"%SystemRoot%\servicing\Packages\%%i"
del hyper-v.txt
Dism /online /enable-feature /featurename:Microsoft-Hyper-V-All /LimitAccess /ALL

保存后,将文本文件后缀修改为 cmd,并且用管理员身份运行,运行完成后输入 y 重启电脑,之后再打开 Hyper-V 就可以运行了。

img

适用于Linux的Windows子系统 & 虚拟机平台

img

4.1.2 wsl 安装 ubuntu

安装

# 设置 wsl2 为默认版本
wsl --set-default-version 2

# 安装 ubuntu
wsl --install -d Ubuntu

# 安装完成后,重新打开的窗口需要输入新的 linux 用户名与密码
# 用户名密码填完后,使用 PowerShell 查看当前版本,确认版本是否为 2,如果为 2 则不用升级
wsl -l -v

升级 wsl2

  • 主要原因:wsl2 版本中拥有完整的 Linux 内核功能,而wsl1 版本中是不完整的 Linux 内核功能。
如果以前已经装过其他 linux 子系统,且 wsl 版本为 1 的,按照以下步骤升级
找到 软件 目录中的 wsl_update_x64.msi 执行并安装
设置 wsl2 为默认版本 wsl --set-default-version 2
查询需要升级的版本 wsl -l -v
选择对应的版本升级 wsl --set-version <第三步查到的名称> 2
输出转换完成后表示成功,通过 wsl -l -v 再次确认版本是否转换成功

4.1.3 安装 Docker Desktop

找到软件中的安装包,直接双击安装即可,所有选项都默认,安装完成后需要重启电脑,电脑重启完毕后再次打开 Docker Desktop,需要接受订阅服务协议才可使用

闪退问题

基于第一步开启对应的三个功能

一直卡在Docker engine starting

如果出现一直卡在 Engine starting,按住 shift 键在任意空白位置右键,打开 Power Shell,并执行如下两行命令

cd "C:\Program Files\Docker\Docker"
./DockerCli.exe -SwitchDaemon

4.1.4 客户端设置

启用 wsl 虚拟机子系统

在设置界面中找到 Resources > WSL Integration 选项
勾选 Enable integration with my default WSL distro

且启用下方你所安装的 linux 子系统,如 Ubuntu

修改完成后,点击右下方的 Apply & restart 按钮重启 Docker

img

配置仓库与镜像

找到设置页面中的 Docker Engine,进去以后修改原先的 json 文件,加入如下内容

insecure-registries:信任的仓库列表,用于 pull/push 镜像
registry-mirrors:   镜像仓库列表,用于提升镜像下载速度

"insecure-registries": [
  "10.0.0.51:5000",
  "10.0.0.51:5001"
],
"registry-mirrors": [
  "https://po13h3y1.mirror.aliyuncs.com",
  "https://registry.docker-cn.com",
  "https://hub-mirror.c.163.com",
  "https://docker.mirrors.ustc.edu.cn"
]

修改完毕后点击右下方的 Apply & restart 按钮

img

💫4.2 IntelliJ IDEA 构建 Docker 镜像

目的:将开发人员的项目构建成为Docker 镜像,然后将Docker 镜像运行成 Docker 容器。

4.2.1 maven 插件

必须要进行 maven 的加速配置可以参考文档:

Maven 加速参考文档:Maven 阿里云镜像加速

4.2.1.1 常见插件
  1. Spring Boot Maven 打包插件内置的 build-image

官方文档:https://docs.spring.io/spring-boot/docs/current/maven-plugin/reference/htmlsingle/#build-image

Spring Boot 2.3 版本后默认集成了用于构建 Maven 镜像的插件,只要是 Spring Boot 项目,就可以直接使用,前提是本地环境中安装了 Docker。

命令:

mvn spring-boot:build-image
# 并不是传统的Dockerfile形式,管理员不需要手动编写Dockerfile
# 该插件会提供相应的配置信息,可以基于提供的配置信息,把需要定制的内容编写在配置文件中
# 使用简单,就意味着封装的程度就更高,层级高,意味着灵活性较低,定制化的功能就较低了

拓展配置:

<plugin>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-maven-plugin</artifactId>
    <configuration>
        <!-- 指定打包后的镜像名 -->
        <imageName>${groupId}/${project.artifactId}:${project.version}</imageName>
        <docker>
            <!-- 配置发布的仓库信息 -->
            <publishRegistry>
                <url>http://10.0.0.51:5000</url>
                <username>admin</username>
                <password>wolfcode</password>
            </publishRegistry>
        </docker>
    </configuration>
</plugin>
  1. Google 的 jib-maven-plugin

Jib 是一个 MavenGradle 插件,用来创建 Docker 镜像。它最大的特点是,你的本地可以没有 Docker 也可以进行构建,同样也不需要编写 Dockerfile 文件,不用改动代码,甚至不用修改 pom.xml 文件,运行如下命令即可:

# 国外使用频率较高,因为使用的Google的地址
# 使用简单,就意味着封装的程度就更高,层级高,意味着灵活性较低,定制化的功能就较低了
mvn compile com.google.cloud.tools:jib-maven-plugin:2.3.0:dockerBuild
  1. Spotify 的 dockerfile-maven-plugin

专门基于 Dockerfile 构建镜像的插件,也是目前市面上用的比较多的镜像构建方式之一。[ 国内使用插件较多,是使用开发人员编写的Dockerfile文件进行构建 ]

<plugin>
    <groupId>com.spotify</groupId>
    <artifactId>dockerfile-maven-plugin</artifactId>
    <version>1.4.13</version>
    <executions>
        <execution>
            <id>default</id>
            <!-- 自定义构建、推送命令 -->
            <goals>
                <goal>build</goal>
                <goal>push</goal>
            </goals>
        </execution>
    </executions>
    <configuration>
        <!-- 打包后的完整镜像名:仓库路径/组织/镜像名 -->
        <repository>10.0.0.51:5000/wolfcode/${project.artifactId}</repository>
        <!-- 镜像版本号 -->
        <tag>${project.version}</tag>
        <!-- 读取 settings.xml 文件中的认证信息 -->
        <useMavenSettingsForAuth>true</useMavenSettingsForAuth>
        <buildArgs>
            <!-- jar 所在目录 -->
            <JAR_FILE>target/${project.artifactId}-${project.version}.jar</JAR_FILE>
        </buildArgs>
    </configuration>
</plugin>

img

  • 查看 Maven 的settings.xml配置文件中的连接镜像仓库的配置

img

4.2.1.2 Dockerfile 配置
## 基础镜像
## AdoptOpenJDK 停止发布 OpenJDK 二进制,而 Eclipse Temurin 是它的延伸,提供更好的稳定性
FROM eclipse-temurin:8-jre

## 作者
MAINTAINER xiaoliu <liugang@wolfcode.cn>

## 定义参数
ARG JAR_FILE

## 创建并进入工作目录
RUN mkdir -p /wolfcode
WORKDIR /wolfcode

## maven 插件构建时得到 buildArgs 种的值
COPY ${JAR_FILE} app.jar

## 设置 TZ 时区
## 设置 JAVA_OPTS 环境变量,可通过 docker run -e "JAVA_OPTS=" 进行覆盖
ENV TZ=Asia/Shanghai JAVA_OPTS="-Xms256m -Xmx256m"

## 暴露端口
EXPOSE 8080

## 容器启动命令
## CMD 第一个参数之后的命令可以在运行时被替换
CMD java ${JAVA_OPTS} -Djava.security.egd=file:/dev/./urandom -jar app.jar

img

在 Dockerfile 中 CMDENTRYPOINT 的扩展性要高得多,因为 CMD 可以被 docker run 后面的参数进行替换。可以实现相应的功能。

查看本地开发环境的 Docker Image 镜像

$ docker images         
REPOSITORY        TAG       IMAGE ID       CREATED         SIZE
eclipse-temurin   8-jre     50d0169500d4   9 days ago      221MB
tomcat            9.0       b8e65a4d736d   16 months ago   680MB
4.2.1.3 构建镜像
# mvn dockerfile:build

img

# 查看构建镜像信息
$ docker images 
REPOSITORY                                       TAG       IMAGE ID       CREATED          SIZE
10.0.0.51:5000/wolfcode/springboot-docker-demo   1.0.0     5f1e4cf8edca   54 seconds ago   241MB
eclipse-temurin                                  8-jre     50d0169500d4   9 days ago       221MB
tomcat                                           9.0       b8e65a4d736d   16 months ago    680MB

$ docker history 10.0.0.51:5000/wolfcode/springboot-docker-demo:1.0.0
IMAGE          CREATED              CREATED BY                                      SIZE      COMMENT
5f1e4cf8edca   About a minute ago   /bin/sh -c #(nop)  CMD ["/bin/sh" "-c" "java…   0B
dcfd3534a64c   About a minute ago   /bin/sh -c #(nop)  EXPOSE 8080                  0B
7c36a50ffaf7   About a minute ago   /bin/sh -c #(nop)  ENV TZ=Asia/Shanghai JAVA…   0B
979358c07b4d   About a minute ago   /bin/sh -c #(nop) COPY file:fc0cd155a74929a2…   19.7MB
b4023efffb6d   About a minute ago   /bin/sh -c #(nop) WORKDIR /wolfcode             0B
db9c2416c218   About a minute ago   |1 JAR_FILE=target/springboot-docker-demo-1.…   0B
ad4967b4b961   About a minute ago   /bin/sh -c #(nop)  ARG JAR_FILE                 0B
8f808c67b682   About a minute ago   /bin/sh -c #(nop)  MAINTAINER xiaoliu <liuga…   0B
50d0169500d4   9 days ago           /bin/sh -c echo Verifying install ...     &&…   0B
<missing>      9 days ago           /bin/sh -c set -eux;     ARCH="$(dpkg --prin…   109MB
<missing>      9 days ago           /bin/sh -c #(nop)  ENV JAVA_VERSION=jdk8u372…   0B
<missing>      9 days ago           /bin/sh -c apt-get update     && DEBIAN_FRON…   34.7MB
<missing>      9 days ago           /bin/sh -c #(nop)  ENV LANG=en_US.UTF-8 LANG…   0B
<missing>      9 days ago           /bin/sh -c #(nop)  ENV PATH=/opt/java/openjd…   0B
<missing>      9 days ago           /bin/sh -c #(nop)  ENV JAVA_HOME=/opt/java/o…   0B
<missing>      2 weeks ago          /bin/sh -c #(nop)  CMD ["/bin/bash"]            0B
<missing>      2 weeks ago          /bin/sh -c #(nop) ADD file:2fc6364d149eccc7f…   77.8MB
<missing>      2 weeks ago          /bin/sh -c #(nop)  LABEL org.opencontainers.…   0B
<missing>      2 weeks ago          /bin/sh -c #(nop)  LABEL org.opencontainers.…   0B
<missing>      2 weeks ago          /bin/sh -c #(nop)  ARG LAUNCHPAD_BUILD_ARCH     0B
<missing>      2 weeks ago          /bin/sh -c #(nop)  ARG RELEASE                  0B
4.2.1.4 推送镜像到仓库

mavensettings.xml 文件的 servers 标签中,增加服务认证配置信息

<server>
  <id>10.0.0.51:5000</id>
  <username>admin</username>
  <password>Admin@h3c</password>
</server>

# mvn dockerfile:push

img

  • IDEA 中的 maven 插件中拥有 “dockerfile” 插件并且其中有"dockerfile:push" 的操作,执行之后就会推送到远程仓库中(使用的是 Nexus 镜像仓库)

img

  • 登录到 Nexus 镜像仓库,查看到推送镜像的情况

img

  • 自动化的将镜像运行成容器[ 需要研究脚本的指令的作用 ]

img

  • docker-deploy.sh脚本文件上传到服务器中
$ mkdir -p /opt/springboot-docker-demo
$ vim docker-deploy.sh
# 参考示例:脚本内容

示例:脚本内容

#!/bin/bash

## 第一个参数:up|start|stop|restart|rm
COMMAND=$1
## app 名称
APP_NAME=$2

## 如果没有给 app 名称,默认就叫 app
if [ -z $APP_NAME ]; then
  APP_NAME="springboot-docker-demo"
fi

## 暴露的端口
EXPOSE_PORT=8888
## 项目/组织
NAMESPACE=wolfcode
## 版本号
TAG=1.0.0

## 仓库地址
REGISTRY_SERVER=10.0.0.51:5000

## 用户名
USERNAME=admin
## 密码
PASSWORD=Admin@h3c

## 镜像名称
IMAGE_NAME="$REGISTRY_SERVER/$NAMESPACE/$APP_NAME:$TAG"

## 使用说明,用来提示输入参数
function usage() {
	echo "Usage: sh docker-deploy.sh [up|start|stop|restart|rm]"
	exit 1
}

## 登录仓库
function login() {
  echo "docker login -u $USERNAME --password-stdin $REGISTRY_SERVER"
  echo "$PASSWORD" | docker login -u $USERNAME --password-stdin $REGISTRY_SERVER
}

## 启动容器
function start() {
  # 检查容器是否存在
  CONTAINER_NAME=$(docker ps | grep "$APP_NAME" | awk '{print $NF}')
  # 存在就不启动了
  if [ -n "$CONTAINER_NAME" ]; then
    echo "container $CONTAINER_NAME aready started..."
    exit 1
  fi
  # 镜像如果不存在需要先登录
  IMAGE=$(docker images | grep "$APP_NAME" | awk '{print $3}')
  if [ -z "$IMAGE" ]; then
    login
  fi
  # 容器不存在就启动
  echo "starting container $APP_NAME..."
  docker run -d --restart=always --name $APP_NAME -p $EXPOSE_PORT:8080 $IMAGE_NAME
  echo "container $APP_NAME started..."
}

## 停止容器
function stop() {
  # 检查容器是否存在
  CONTAINER_NAME=$(docker ps | grep "$APP_NAME" | awk '{print $NF}')

  # 不存在就不需要停止
  if [ -z "$CONTAINER_NAME" ]; then
    echo "container $CONTAINER_NAME not running..."
    exit 1
  fi

  # 存在就停止容器
  echo "stoping container $APP_NAME..."
  docker stop $CONTAINER_NAME
  echo "container $APP_NAME stopted..."
}

## 重启容器
function restart() {
  # 先停止
  stop
  # 再启动
  start
}

## 删除容器、镜像
function rm() {
  # 获取容器名称
  CONTAINER_NAME=$(docker ps | grep "$APP_NAME" | awk '{print $NF}')
  if [ -n "$CONTAINER_NAME" ]; then
    # 停止容器
    stop
    # 删除容器
    echo "removing container $APP_NAME..."
    docker rm $CONTAINER_NAME
    echo "container $APP_NAME removed..."
  fi

  # 获取镜像 id
  IMAGE=$(docker images | grep "$APP_NAME" | awk '{print $3}')
  if [ -n "$IMAGE" ]; then
    # 删除镜像
    echo "removing image $IMAGE..."
    docker rmi $IMAGE
    echo "image $IMAGE removed..."
  fi
}

# 重新拉取镜像并启动容器
function up() {
  # 删除旧的镜像与容器
  rm
  # 拉取新的镜像并启动容器
  start
}

# 根据输入参数,选择执行对应方法,不输入则执行使用说明
case "$COMMAND" in
"up")
	up
;;
"start")
	start
;;
"stop")
	stop
;;
"restart")
	restart
;;
"rm")
	rm
;;
*)
	usage
;;
esac
  • 执行脚本
$ chmod +x docker-deploy.sh
$ sh docker-deploy.sh up

# 查看镜像的情况
$ docker images 10.0.0.51:5000/wolfcode/springboot-docker-demo
REPOSITORY                                       TAG       IMAGE ID       CREATED          SIZE
10.0.0.51:5000/wolfcode/springboot-docker-demo   1.0.0     5f1e4cf8edca   43 minutes ago   241MB

# 查看运行容器的情况
$ docker ps -l
CONTAINER ID   IMAGE                                                  COMMAND                  CREATED          STATUS          PORTS                                       NAMES
75a3ed93a06c   10.0.0.51:5000/wolfcode/springboot-docker-demo:1.0.0   "/bin/sh -c 'java ${…"   30 seconds ago   Up 26 seconds   0.0.0.0:8888->8080/tcp, :::8888->8080/tcp   springboot-docker-demo

img

  • 访问页面
$ curl 10.0.0.51:8888
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Spring Boot Docker Demo</title>
</head>
<body>
<h1>Spring Boot in Docker...</h1>
</body>
</html>

$ curl 10.0.0.51:8888/hello
Spring Boot in Docker...
  • IDEA 新增接口代码,并重新进行package打包构建镜像,然后进行镜像的推送到 Nexus 镜像仓库中[ 执行 maven 插件中拥有 “dockerfile” 插件并且其中有"dockerfile:push" 的操作 ]

img

# 在服务器中执行脚本docker-deploy.sh
$ bash docker-deploy.sh up
$ curl 10.0.0.51:8888/new
New Interface...

4.2.2 Alibaba Cloud Toolkit

Alibaba Cloud Toolkit(后文简称Cloud Toolkit)可以帮助开发者更高效地部署、测试、开发和诊断应用。Cloud Toolkit与主流IDE及阿里云其他产品无缝集成,帮助您大大简化应用部署到服务器,尤其是阿里云服务器中的操作。您还可以通过其内嵌的Arthas程序诊断、Terminal Shell终端和MySQL执行器等工具,简化应用开发、测试和诊断的过程。

官方站点:什么是Alibaba Cloud Toolkit

img

产品功能

  • 部署应用

    • 部署应用到ECS:完成编码后,利用Cloud Toolkit快速将应用部署至ECS指定目录。
    • 部署应用到EDAS:将本地代码和云端应用进行关联后,可以实现自动化的部署。
    • 部署应用到Kubernetes:将本地代码和云端容器进行关联后,可以实现自动化的镜像上传和部署。
    • 部署应用到远程服务器:支持SSH标准协议,可以将应用部署到任意机器。
  • 内置终端Terminal:在本地IDE内,开发者可以直接通过内置的终端Terminal,快速登录所有支持标准SSH协议的机器。

  • 文件上传:在本地IDE内,开发者可以一键将本地文件或者远程URL上传到服务器指定目录。

  • SLS日志查看:在本地IDE内,开发者可以查看/分析阿里云的SLS日志。

  • 内置数据库SQL Console:在本地IDE内,开发者可以浏览阿里云的RDS资源。若已配置用户名和密码,可通过内置的SQL Console连接上RDS实例,并快速执行SQL语句。

  • Arthas诊断:在本地IDE中即可使用Arthas来实现远程诊断。

  • 创建Dubbo应用:在本地IDE中快速创建Dubbo应用。

  • SSH代理功能:可使用Cloud Toolkit支持SSH代理的功能,通过添加代理机、添加部署机器和设置代理等操作,快速打通网络环境。

4.2.2.1 安装CouTookit

打开 IDEA 设置,进入 plugins 菜单,在插件市场中搜索 Alibaba Cloud Toolkit,找到后下载并重启 IDEA。

  • 重启 IDEA 之后进行添加主机

img

添加主机完成

img

  • 注意编辑 IDEA 中 pom.xml 文件中的对 Nexus 地址的情况

img

  • 并且在 pom.xml 文件中添加内容[ 否则会出现由于 maven-plugin 版本过低导致构建镜像失败 ]
<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-war-plugin</artifactId>
            <version>3.2.2</version>
        </plugin>
    <plugins>
<build>
  • IDEA 中的 “maven” 选项中的 package进行对项目打包并进行构建镜像

img

  • 可以查看到本地镜像的情况
$ docker images 
REPOSITORY                                       TAG            IMAGE ID       CREATED         SIZE
10.0.0.51:5000/wolfcode/javaweb-docker-demo      1.0-SNAPSHOT   227fdd3bad4e   6 minutes ago   680MB
10.0.0.51:5000/wolfcode/springboot-docker-demo   1.0.0          5f1e4cf8edca   2 hours ago     241MB
eclipse-temurin                                  8-jre          50d0169500d4   9 days ago      221MB
tomcat                                           9.0            b8e65a4d736d   16 months ago   680MB

# 查看镜像的历史记录
$ docker history 10.0.0.51:5000/wolfcode/javaweb-docker-demo:1.0-SNAPSHOT
IMAGE          CREATED         CREATED BY                                      SIZE      COMMENT
227fdd3bad4e   8 minutes ago   /bin/sh -c #(nop)  CMD ["/bin/sh" "-c" "bin/…   0B
950d2ee47fb8   8 minutes ago   /bin/sh -c #(nop) WORKDIR /usr/local/tomcat/    0B
ad356019409c   8 minutes ago   /bin/sh -c #(nop) COPY file:a62016ebf68d72cb…   4.08kB
04890adc5c7f   8 minutes ago   /bin/sh -c #(nop)  ARG JAR_FILE                 0B
61fc3683f82e   8 minutes ago   /bin/sh -c #(nop) WORKDIR /usr/local/tomcat/…   0B
9715085bc38f   8 minutes ago   /bin/sh -c #(nop)  MAINTAINER xiaoliu<liugan…   0B
b8e65a4d736d   16 months ago   /bin/sh -c #(nop)  CMD ["catalina.sh" "run"]    0B
<missing>      16 months ago   /bin/sh -c #(nop)  EXPOSE 8080                  0B
<missing>      16 months ago   /bin/sh -c set -eux;  nativeLines="$(catalin…   0B
<missing>      16 months ago   /bin/sh -c set -eux;   savedAptMark="$(apt-m…   20.2MB
<missing>      16 months ago   /bin/sh -c #(nop)  ENV TOMCAT_SHA512=b4c2c85…   0B
<missing>      16 months ago   /bin/sh -c #(nop)  ENV TOMCAT_VERSION=9.0.56    0B
<missing>      16 months ago   /bin/sh -c #(nop)  ENV TOMCAT_MAJOR=9           0B
<missing>      16 months ago   /bin/sh -c #(nop)  ENV GPG_KEYS=48F8E69F6390…   0B
<missing>      16 months ago   /bin/sh -c #(nop)  ENV LD_LIBRARY_PATH=/usr/…   0B
<missing>      16 months ago   /bin/sh -c #(nop)  ENV TOMCAT_NATIVE_LIBDIR=…   0B
<missing>      16 months ago   /bin/sh -c #(nop) WORKDIR /usr/local/tomcat     0B
<missing>      16 months ago   /bin/sh -c mkdir -p "$CATALINA_HOME"            0B
<missing>      16 months ago   /bin/sh -c #(nop)  ENV PATH=/usr/local/tomca…   0B
<missing>      16 months ago   /bin/sh -c #(nop)  ENV CATALINA_HOME=/usr/lo…   0B
<missing>      16 months ago   /bin/sh -c #(nop)  CMD ["jshell"]               0B
<missing>      16 months ago   /bin/sh -c set -eux;   arch="$(dpkg --print-…   343MB
<missing>      16 months ago   /bin/sh -c #(nop)  ENV JAVA_VERSION=11.0.13     0B
<missing>      16 months ago   /bin/sh -c #(nop)  ENV LANG=C.UTF-8             0B
<missing>      16 months ago   /bin/sh -c #(nop)  ENV PATH=/usr/local/openj…   0B
<missing>      16 months ago   /bin/sh -c { echo '#/bin/sh'; echo 'echo "$J…   27B
<missing>      16 months ago   /bin/sh -c #(nop)  ENV JAVA_HOME=/usr/local/…   0B
<missing>      16 months ago   /bin/sh -c set -eux;  apt-get update;  apt-g…   11.3MB
<missing>      16 months ago   /bin/sh -c apt-get update && apt-get install…   152MB
<missing>      16 months ago   /bin/sh -c set -ex;  if ! command -v gpg > /…   18.9MB
<missing>      16 months ago   /bin/sh -c set -eux;  apt-get update;  apt-g…   10.7MB
<missing>      16 months ago   /bin/sh -c #(nop)  CMD ["bash"]                 0B
<missing>      16 months ago   /bin/sh -c #(nop) ADD file:c03517c5ddbed4053…   124MB
  • IDEA 中的 maven 插件中拥有 “dockerfile” 插件并且其中有"dockerfile:push" 的操作,执行之后就会推送到远程仓库中(使用的是 Nexus 镜像仓库)

img

  • 登录到 Nexus 镜像仓库,查看到推送镜像的情况

img

  • docker-deploy.sh脚本文件上传到服务器中
$ mkdir -p /opt/javaweb-docker-demo
$ vim docker-deploy.sh
# 参考示例:脚本内容

示例:脚本内容

#!/bin/bash

## 第一个参数:up|start|stop|restart|rm
COMMAND=$1
## app 名称
APP_NAME=$2

## 如果没有给 app 名称,默认就叫 app
if [ -z $APP_NAME ]; then
  APP_NAME="javaweb-docker-demo"
fi

## 暴露的端口
EXPOSE_PORT=8808
## 项目/组织
NAMESPACE=wolfcode
## 版本号
TAG=1.0-SNAPSHOT

## 仓库地址
REGISTRY_SERVER=10.0.0.51:5000

## 用户名
USERNAME=admin
## 密码
PASSWORD=Admin@h3c

## 镜像名称
IMAGE_NAME="$REGISTRY_SERVER/$NAMESPACE/$APP_NAME:$TAG"

## 使用说明,用来提示输入参数
function usage() {
	echo "Usage: sh docker-deploy.sh [up|start|stop|restart|rm]"
	exit 1
}

## 登录仓库
function login() {
  echo "docker login -u $USERNAME --password-stdin $REGISTRY_SERVER"
  echo "$PASSWORD" | docker login -u $USERNAME --password-stdin $REGISTRY_SERVER
}

## 启动容器
function start() {
  # 检查容器是否存在
  CONTAINER_NAME=$(docker ps | grep "$APP_NAME" | awk '{print $NF}')
  # 存在就不启动了
  if [ -n "$CONTAINER_NAME" ]; then
    echo "container $CONTAINER_NAME aready started..."
    exit 1
  fi
  # 镜像如果不存在需要先登录
  IMAGE=$(docker images | grep "$APP_NAME" | awk '{print $3}')
  if [ -z "$IMAGE" ]; then
    login
  fi
  # 容器不存在就启动
  echo "starting container $APP_NAME..."
  docker run -d --restart=always --name $APP_NAME -p $EXPOSE_PORT:8080 $IMAGE_NAME
  echo "container $APP_NAME started..."
}

## 停止容器
function stop() {
  # 检查容器是否存在
  CONTAINER_NAME=$(docker ps | grep "$APP_NAME" | awk '{print $NF}')

  # 不存在就不需要停止
  if [ -z "$CONTAINER_NAME" ]; then
    echo "container $CONTAINER_NAME not running..."
    exit 1
  fi

  # 存在就停止容器
  echo "stoping container $APP_NAME..."
  docker stop $CONTAINER_NAME
  echo "container $APP_NAME stopted..."
}

## 重启容器
function restart() {
  # 先停止
  stop
  # 再启动
  start
}

## 删除容器、镜像
function rm() {
  # 获取容器名称
  CONTAINER_NAME=$(docker ps | grep "$APP_NAME" | awk '{print $NF}')
  if [ -n "$CONTAINER_NAME" ]; then
    # 停止容器
    stop
    # 删除容器
    echo "removing container $APP_NAME..."
    docker rm $CONTAINER_NAME
    echo "container $APP_NAME removed..."
  fi

  # 获取镜像 id
  IMAGE=$(docker images | grep "$APP_NAME" | awk '{print $3}')
  if [ -n "$IMAGE" ]; then
    # 删除镜像
    echo "removing image $IMAGE..."
    docker rmi $IMAGE
    echo "image $IMAGE removed..."
  fi
}

# 重新拉取镜像并启动容器
function up() {
  # 删除旧的镜像与容器
  rm
  # 拉取新的镜像并启动容器
  start
}

# 根据输入参数,选择执行对应方法,不输入则执行使用说明
case "$COMMAND" in
"up")
	up
;;
"start")
	start
;;
"stop")
	stop
;;
"restart")
	restart
;;
"rm")
	rm
;;
*)
	usage
;;
esac
  • 执行脚本
$ chmod +x docker-deploy.sh
$ docker-deploy.sh up

# 查看镜像的情况
$ docker images 10.0.0.51:5000/wolfcode/javaweb-docker-demo:1.0-SNAPSHOT 
REPOSITORY                                    TAG            IMAGE ID       CREATED          SIZE
10.0.0.51:5000/wolfcode/javaweb-docker-demo   1.0-SNAPSHOT   227fdd3bad4e   18 minutes ago   680MB

# 查看运行容器的情况
$ docker ps -l 
CONTAINER ID   IMAGE                                                      COMMAND                  CREATED          STATUS          PORTS                                       NAMES
7ab9e672f40c   10.0.0.51:5000/wolfcode/javaweb-docker-demo:1.0-SNAPSHOT   "/bin/sh -c 'bin/cat…"   45 seconds ago   Up 44 seconds   0.0.0.0:8808->8080/tcp, :::8808->8080/tcp   javaweb-docker-demo

img

  • 访问页面
$ curl 10.0.0.51:8808
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Java Web 项目 Docker 容器化部署</title>
</head>
<body>
<h1>Java Web: Hello Docker!!!</h1>
</body>
</html>

$ curl 10.0.0.51:8808/hello
Java Web: Hello Docker!!!
  • IDEA 修改脚本文件中暴露的端口

img

  • 利用Alibaba Cloud Tookit的插件将脚本文件进行上传到服务器中,并重新进行package打包构建镜像

img

  • 利用Alibaba Cloud Tookit的插件远程登录到远程服务器中,就可以执行脚本进行运行

img

img

# 在服务器中执行脚本docker-deploy.sh
$ bash docker-deploy.sh up

$ curl 10.0.0.51:8808
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Java Web 项目 Docker 容器化部署</title>
</head>
<body>
<h1>Java Web: Hello Docker!!!</h1>
</body>
</html>

$ curl 10.0.0.51:8808/hello
Java Web: Hello Docker!!!
4.2.2.2 部看应用到境像仓库

部署到 ACR

  1. 在部署参数页面选择 **Alibaba Cloud Container Registry**

  2. 选择**地域****命名空间****镜像仓库**

  3. **Advanced**下拉选项中选择网络类型。

    1. **Internet**:公有网络。
    2. **VPC Network**:VPC网络。
    3. **Classic Network**:经典网络。
  4. 先单击 **Apply**,然后单击 **Run**

部看到私服仓库

  1. 在部署参数页面选择 **Custom Container Registry**
  2. 单击界面右侧的 **Add**,配置Registry信息。
  3. **Registry** 页面配置镜像仓库 **Name**、**Address**、**Username** 和 **Password**,单击 **Apply**,然后单击 **OK**
  4. **Repository** 对话框填入您的镜像地址。
  5. 先单击 **Apply**,然后单击 **Run**
4.2.2.3 管理远程服务器

添加服务器

已有支持 SSH 协议的远程服务器,可以直接添加;

**添加已有远程服务器**
  1. 在IntelliJ IDEA顶部菜单栏中选择**Tools > Alibaba Cloud > Alibaba Cloud View > Host**

  2. **Host**页签中单击**Add Host**

  3. **Add Host**对话框填写Host相关信息,然后单击**Test Connection**来测试是否能成功连接服务器。若成功连接后单击**Add**

    1. 添加成功后,远程服务器将出现在**Host**页签中。

上传文件

  1. **Host**或者**Alibaba Cloud ECS**页签中单击目标服务器**Actions**区域的**Upload**
  2. **Upload**对话框中选择需上传的文件或文件夹,并设置部署参数,然后单击**Upload**

下载文件

  1. 在IntelliJ IDEA菜单栏选择 **Tools > Alibaba Cloud > Alibaba Cloud View > Host**
  2. **Host**列表右侧**Action**选择**Remote Files**
  3. 您可根据需求选择刷新、上传和下载远程服务器上的文件。

💫4.3 镜像构建项目实战

4.3.1 Java Web 项目

使用项目地址:

链接:https://pan.baidu.com/s/1nYxMvR9or496BqSh219DCg

提取码:yyds

# 基于 Tomcat9 作为基础镜像
FROM tomcat:9.0

# 作者
MAINTAINER xiaoliu<liugang@wolfcode.cn>

# 进入 Tomcat 部署目录
WORKDIR /usr/local/tomcat/webapps

# 定义参数
ARG JAR_FILE

# 将 war 包拷贝到 tomcat 中,并且改名为 ROOT
COPY ${JAR_FILE} ROOT.war

# 回到 Tomcat 根目录设置工作目录
WORKDIR /usr/local/tomcat/

# 启动时运行命令
CMD bin/catalina.sh run

4.3.2 Spring Boot 项目

可以参考之前章节的过程:

  • 4.2.1.1 常见插件
  • 4.2.1.2 Dockerfile 配置
  • 4.2.1.3 构建镜像
  • 4.2.1.4 推送镜像到仓库

使用项目地址:

链接:https://pan.baidu.com/s/1nYxMvR9or496BqSh219DCg

提取码:yyds

## 基础镜像
## AdoptOpenJDK 停止发布 OpenJDK 二进制,而 Eclipse Temurin 是它的延伸,提供更好的稳定性
FROM eclipse-temurin:8-jre

## 作者
MAINTAINER xiaoliu <liugang@wolfcode.cn>

## 定义参数
ARG JAR_FILE
## 创建并进入工作目录
RUN mkdir -p /wolfcode
WORKDIR /wolfcode

## maven 插件构建时得到 buildArgs 种的值
COPY ${JAR_FILE} app.jar

## 设置 TZ 时区
## 设置 JAVA_OPTS 环境变量,可通过 docker run -e "JAVA_OPTS=" 进行覆盖
ENV TZ=Asia/Shanghai JAVA_OPTS="-Xms256m -Xmx256m"

## 暴露端口
EXPOSE 8080

## 容器启动命令
## CMD 第一个参数之后的命令可以在运行时被替换
CMD java ${JAVA_OPTS} -Djava.security.egd=file:/dev/./urandom -jar app.jar

4.3.3 Spring Cloud 微服务项目

使用项目地址:

链接:https://pan.baidu.com/s/1nYxMvR9or496BqSh219DCg

提取码:yyds

项目结构图:

img

4.3.3.1 部署流程
4.3.3.1.1 容器编排

docker-compose | docker-swarm

4.3.3.1.2 Dockerfile编写

针对每一个服务都需要编写自定义的 Dockerfile,需要对所有服务的 Dockerfile 文件进行一个统一的管理。

4.3.3.1.3 网络问题

自定义网络,或者利用 links 属性,将两个容器连接起来,以上两种方案都可以实现基于容器名称的访问

4.3.3.1.4 日志收集问题

ELK:利用 LagstashFileBeat 进行数据收集,将数据存入 ES,通过 Kibana 进行统一的数据可视化展示

4.3.3.1.5 监控问题

应用/容器监控,健康状况、资源使用情况都需要进行监控,基于普罗米修斯实现各个类型的监控

4.3.3.2 Cloud Toolkit 最佳实践

项目代码列表

由于是微服务的架构,整体项目结构相对来说是更加复杂的;不可能像之前的单体项目一样,在每一个需要部署的项目里面,比如在 pom.xml 进行添加镜像构建的插件,然后在一边打包一边构建镜像。间接了RuoYi若依的开源项目。在真正公司开发的时候,更多的讲究效率,能够有现成的脚手架是很不错的选择。

Docker 构建项目结构规划解析

  • 将项目的内容和 Docker 相关的 Dockerfile、Docker-Compose 配置文件进行分离。
  • docker-compose.yml 是所有容器的一个应用编排管理
  • 主要部署的基础设施:mysql(数据库)、nacos(注册中心 | 配置中心)、redis(缓存数据库)

img

范例:website.conf.nginx.conf 中的 nginx.conf 的文件内容解析

worker_processes  1;

events {
    worker_connections  1024;
}

http {
    include       mime.types;
    default_type  application/octet-stream;
    sendfile        on;
    keepalive_timeout  65;

    server {
        listen       80;
        server_name  localhost;

        # 配置首页的访问路径
		location / {
            root   /home/trip/projects/trip-ui;
#			try_files $uri $uri/ /index.html;
            index  index.html index.htm;
        }

        # 配置接口的反向代理
		location /prod-api/{
			proxy_set_header Host $http_host;
			proxy_set_header X-Real-IP $remote_addr;
			proxy_set_header REMOTE-HOST $remote_addr;
			proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
			# 所有的接口请求都是需要通过网关的
			# 所有前端发起请求以后还是请求在nginx上面,nginx基于一个请求路径的一个标识进行反向代理
			proxy_pass http://trip-gateway:9000/;
			# website 是依赖于 gateway 网关
		}

        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }
    }
}

注意:

项目中的配置内容不是固定写法,而是需要结合实际的开发测试生产环境中的需求进行调整

范例:docker-compose.yml 内容的解析

version: '2.4'
services:
  trip-nacos: # Nacos 的部署
    container_name: trip-nacos # 配置容器名称,方便通过名称来进行网络通信
    image: nacos/nacos-server  # 使用的镜像
    build:
      context: ./nacos  # 使用 Dockerfile 的上下文环境
    environment:
      - MODE=standalone # 配置容器的环境变量
    volumes: # 数据卷配置
      - ./nacos/logs/:/home/nacos/logs
      - ./nacos/conf/application.properties:/home/nacos/conf/application.properties
    ports:   # 暴露的端口(包括健康检测的端口)
      - "8848:8848"
      - "9848:9848"
      - "9849:9849"
    depends_on: # 依赖的服务
      - trip-mysql

  trip-mysql: # MySQL 的部署
    container_name: trip-mysql # 配置容器名称,方便通过名称来进行网络通信
    image: mysql:5.7           # 使用的镜像
    build:
      context: ./mysql # 使用 Dockerfile 的上下文环境
    ports:   # 暴露的端口
      - "3306:3306"
    volumes: # 数据卷配置
      - ./mysql/conf:/etc/mysql/conf.d
      - ./mysql/logs:/logs
      - ./mysql/data:/var/lib/mysql
    command: [ # 容器启动运行的命令
      'mysqld',
      '--innodb-buffer-pool-size=80M',
      '--character-set-server=utf8mb4',
      '--collation-server=utf8mb4_unicode_ci',
      '--default-time-zone=+8:00',
      '--lower-case-table-names=1'
    ]
    environment: # 配置容器的环境变量
      MYSQL_DATABASE: 'trip-cloud'
      MYSQL_ROOT_PASSWORD: 'admin'

  trip-redis:    # Redis 的部署
    container_name: trip-redis # 配置容器名称,方便通过名称来进行网络通信
    image: redis               # 使用的镜像
    build:
      context: ./redis # 使用 Dockerfile 的上下文环境
    ports:   # 暴露的端口
      - "6379:6379"
    volumes: # 数据卷配置
      - ./redis/conf/redis.conf:/home/trip/redis/redis.conf
      - ./redis/data:/data
    command: redis-server /home/trip/redis/redis.conf # 容器启动运行的命令

  trip-website: # Nginx 的部署
    container_name: trip-website # 配置容器名称,方便通过名称来进行网络通信
    image: nginx                 # 使用的镜像
    build:
      context: ./website # 使用 Dockerfile 的上下文环境
    ports:   # 暴露的端口
      - "80:80"
    volumes: # 数据卷配置
      - ./website/html/dist:/home/trip/projects/trip-ui
      - ./website/conf/nginx.conf:/etc/nginx/nginx.conf
      - ./website/logs:/var/log/nginx
      - ./website/conf.d:/etc/nginx/conf.d
    depends_on: # 依赖的服务
      - trip-gateway
    links:      # links 关联的服务,可以使用容器的主机名进行通信
      - trip-gateway

  trip-gateway: # 网关服务
    container_name: trip-gateway # 配置容器名称,方便通过名称来进行网络通信
    build: # 使用 Dockerfile 的上下文环境
      context: ./trip/gateway
      dockerfile: dockerfile
    ports: # 暴露的端口
      - "9000:9000"
    depends_on: # 依赖的服务
      - trip-redis
    links: # links 关联的服务,可以使用容器的主机名进行通信
      - trip-redis

  trip-user: # 用户服务
    container_name: trip-user # 配置容器名称,方便通过名称来进行网络通信
    build: # 使用 Dockerfile 的上下文环境
      context: ./trip/user
      dockerfile: dockerfile
    ports: # 暴露的端口
      - "9200:9200"
    depends_on: # 依赖的服务
      - trip-redis
      - trip-mysql
    links: # links 关联的服务,可以使用容器的主机名进行通信
      - trip-redis
      - trip-mysql

  trip-article: # 文章服务
    container_name: trip-article # 配置容器名称,方便通过名称来进行网络通信
    build: # 使用 Dockerfile 的上下文环境
      context: ./trip/article
      dockerfile: dockerfile
    ports: # 暴露的端口
      - "8060:8060"
    depends_on: # 依赖的服务
      - trip-redis
      - trip-mysql
      - trip-user
    links: # links 关联的服务,可以使用容器的主机名进行通信
      - trip-redis
      - trip-mysql
      - trip-user

--link 和 Docker-Compose 中的 links 的参数会在后期被 Docker 遗弃。

官方文档:https://docs.docker.com/compose/compose-file/compose-file-v3/#links

img

4.3.3.2.1 部署微服务多模块

需要将整个项目的配置文件和资料要准备好

img

微服务项目的部署流程:

  • SpringBoot 的项目需要添加依赖

img

  • 使用 Alibaba Cloud Toolkit 插件上传项目代码

img

img

  • 运行 deploy.sh 脚本信息

img

# 部署基础设施服务
$ sh deploy.sh base
$ docker-compose ps 
   Name                 Command               State                                                              Ports                                                            
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
trip-mysql   docker-entrypoint.sh mysql ...   Up      0.0.0.0:3306->3306/tcp,:::3306->3306/tcp, 33060/tcp                                                                         
trip-nacos   bin/docker-startup.sh            Up      0.0.0.0:8848->8848/tcp,:::8848->8848/tcp, 0.0.0.0:9848->9848/tcp,:::9848->9848/tcp, 0.0.0.0:9849->9849/tcp,:::9849->9849/tcp
trip-redis   docker-entrypoint.sh redis ...   Up      0.0.0.0:6379->6379/tcp,:::6379->6379/tcp

# 需要前提解压website中的html.zip的压缩包
$ unzip html.zip

# 部署启动应用程序模块
$ sh deploy.sh services
$ docker-compose ps 
    Name                  Command               State                                                              Ports                                                            
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
trip-article   java -jar trip-article.jar       Up      0.0.0.0:8060->8060/tcp,:::8060->8060/tcp                                                                                    
trip-gateway   java -jar trip-gateway.jar       Up      0.0.0.0:9000->9000/tcp,:::9000->9000/tcp                                                                                    
trip-mysql     docker-entrypoint.sh mysql ...   Up      0.0.0.0:3306->3306/tcp,:::3306->3306/tcp, 33060/tcp                                                                         
trip-nacos     bin/docker-startup.sh            Up      0.0.0.0:8848->8848/tcp,:::8848->8848/tcp, 0.0.0.0:9848->9848/tcp,:::9848->9848/tcp, 0.0.0.0:9849->9849/tcp,:::9849->9849/tcp
trip-redis     docker-entrypoint.sh redis ...   Up      0.0.0.0:6379->6379/tcp,:::6379->6379/tcp                                                                                    
trip-user      java -jar trip-user.jar          Up      0.0.0.0:9200->9200/tcp,:::9200->9200/tcp                                                                                    
trip-website   /docker-entrypoint.sh ngin ...   Up      0.0.0.0:80->80/tcp,:::80->80/tcp

通过浏览器访问服务器IP地址,就可以查看到相应的微服务项目

img

4.3.3.2.2 查看远程日志
docker-compose logs [服务名]
docker-compose logs -f [服务名]

学技术不能太钻牛角尖,要从深度和广度两个方面是去来看待学习

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Dark_Ice_

你的支持是我创作的核动力。

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值