docker 错误记录

1. 基本概念

一款容器化部署工具,基本思想是每个应用都在一个容器中运行,这个容器类似于一个独立的系统(也可以看做是低配一点的虚拟机),容器与容器间相互隔绝互不干扰。一台服务器上可以运行多个容器,容器可以随时停止。使用docker便于我们可以更好地管理我们应用的环境。

学习目的:如何构建一个镜像,掌握如何使用docker部署一个java项目,进阶一点可以尝试部署一个集群
核心概念:镜像,容器,数据卷,容器间的网络…

ps:基本知识可以参考黑马哥的docker文档

2.部署java项目中遇到的问题

  1. Docker官方提供了一个专门管理、存储镜像的网站,并对外开放了镜像上传、下载的权利。Docker官方提供了一些基础镜像,然后各大软件公司又在基础镜像基础上,制作了自家软件的镜像,全部都存放在这个网站。这个网站就成了Docker镜像交流的社区:https://hub.docker.com,这个网站需要梯子,一般我们会使用国内的一些第三方镜像仓库(问ai),一方面不需要梯子,另一方面下载镜像速度快,不然可能要等很久(真实经历…)

  2. 当我们下载了一些已有的成熟的镜像时(如mysql),有些指令该镜像会认为不需要使用而没有设置,所以如果我们在镜像内部使用某个Linux命令却无法使用时,可能就是因为这个原因.而且你去用安装命令好像也会安装失败.(我就失败了,大家可以试一试行不行)

  3. 自定义java项目镜像时基础镜像可以直接选择使用openJDK21(版本号看自己选择),或者跟黑马视频一样使用centOS7+jdk21的压缩包.我是压缩包打开不了就去问ai改用成openJDK了.

  4. 将java项目打包成jar包的时候要注意把mysql,redis等配置提前修改:

    注意:配置完后用maven进行打包操作时记得禁用test,因为你改变了redis和mysql的连接方式,进行测试会报错说找不到mysql.

    datasource:
      driver-class-name: com.mysql.cj.jdbc.Driver
      //连接改成mysql和下面改成redis是因为后面会把他们放到同一个网络中可以直接用容器名访问.
      //端口号注意是容器内的端口号.
      url: jdbc:mysql://mysql:3306/community
      username: root
      password: 123
    
    data:
      redis:
        host: redis
        port: 6379
        database: 0
        timeout: 5000ms
    
  5. 部署多个容器所需要的文件(以我的项目为例):mysql文件夹,redis文件夹,Dockerfile(不带任何后缀), docker-compose.yml , myapp.jar. mysql文件夹和redis文件夹里面放的是空文件夹(mysql中的init放有.sql文件,用于导入数据库数据的).docker-compose.yml 和Dockerfile文件可以使用ai生成,但是需要辨析因为可能有很多问题,还有ai自动生成的容器内目录不一定正确,最好上镜像仓库网站查询一下最为稳妥.

    放一下我的例子(第一次部署,有许多不足,但我主要也是达成目的为目标,可以再添加很多东西,这个有需要自己AI):

    Dockerfile:

    #使用官方OpenJDK 21镜像作为基础
    
    FROM openjdk:21-slim
    
    #设置工作目录
    
    WORKDIR /app
    
    #将JAR文件复制到容器中
    
    COPY myapp.jar app.jar
    
    #暴露应用端口
    
    EXPOSE 8080
    
    #启动命令,可以根据需要添加JVM参数
    
    ENTRYPOINT ["java", "-jar", "app.jar"]
    

    docker-compose.yml

    services:
      mysql:
        image: mysql:8  # 使用官方MySQL 8镜像
        container_name: mysql
        ports:
          - "3307:3306"  # 宿主机3307映射容器3306
        environment:
          TZ: Asia/Shanghai
          MYSQL_ROOT_PASSWORD: 123  # 建议生产环境使用更复杂密码
          MYSQL_DATABASE: community  # 可选:自动创建数据库,避免手动创建
        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:
          - nowcoder-net
        restart: always  # 容器故障自动重启
    
      redis:
        image: redis:6.2.6  
        container_name: redis
        ports:
          - "6380:6379"  # 宿主机6380映射容器6379
        volumes:
          - "/usr/local/app/redis/data:/data"
        environment:
          - REDIS_PROTECTED_MODE=no   # 指定配置文件启动
        networks:
          - nowcoder-net
        restart: always  # 容器故障自动重启
    
      myapp:
        build: 
          context: .  # 当前目录作为构建上下文
          dockerfile: Dockerfile  # 指定Dockerfile路径
        container_name: nowcoder
        ports:
          - "8080:8080"  # 宿主机8080映射容器8080
        networks:
          - nowcoder-net
        depends_on:
          - mysql  # 确保mysql启动后再启动app
          - redis  # 确保redis启动后再启动app
        restart: always  # 容器故障自动重启
        environment:
          TZ: Asia/Shanghai  # 同步时区
    
    networks:
      nowcoder-net:
        name: nowcoder-net 
    
    
    
  6. 部署命令: docker compose up -d

    注意:当你部署完项目后如果你要更换jar包:Docker 容器是基于镜像运行的,而镜像在构建时会将当时的 JAR 包打包进去。当你修改了本地的 JAR 包后:已存在的镜像不会自动更新(镜像一旦构建就是只读的)用 docker-compose up 启动时,Docker 会优先使用已有的旧镜像,不会主动检测本地 JAR 包的变化。因此,修改 JAR 包后,必须重新构建镜像,才能让容器运行新版本的代码。

    正确的操作步骤(修改 JAR 包后)

    1. 确保修改后的 JAR 包已更新到构建目录

    假设你的 Dockerfile 中用 COPY myapp.jar app.jar 复制 JAR 包,需确保本地的 myapp.jar 已替换为修改后的新版本。

    2. 重新构建镜像并启动容器
    # 停止并删除旧容器和网络(保留数据卷)
    docker-compose down
    
    # 重新构建镜像并启动(--build 会触发重新构建)
    docker-compose up -d --build
    
    • --build 作用:强制重新执行 Dockerfile,将新的 JAR 包打包到镜像中;
    • 启动后,容器会基于新镜像运行,此时修改后的 JAR 包才会生效。
    3. 验证是否生效

    查看容器日志,确认新版本的代码已运行:

    # 查看应用日志,搜索新版本特征(如修改的日志输出、功能等)
    docker logs -f nowcoder
    
Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐