1.快速入门

1.1、安装 Docker

  • 卸载旧版

    yum remove docker \
        docker-client \
        docker-client-latest \
        docker-common \
        docker-latest \
        docker-latest-logrotate \
        docker-logrotate \
        docker-engine
    
  • 配置 docker 的 yum 库

    安装 yum 工具

    yum install -y yum-utils
    

    安装成功后,执行命令,配置 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 containerd.io docker-buildx-plugin docker-compose-plugin
    
  • 校验

    docker ps
    

    image-20231005190104396

可以通过 systemctl 命令来启动和停止重启等操作

  • 配置镜像加速

  • 开通镜像服务

    image-20231005190345462

    image-20231005190359420

  • 配置镜像加速

    image-20231005190423603

  • 配置文档说明具体命令

    # 创建目录
    mkdir -p /etc/docker
    
    # 复制内容,注意把其中的镜像加速地址改成你自己的
    tee /etc/docker/daemon.json <<-'EOF'
    {
      "registry-mirrors": ["https://xxxx.mirror.aliyuncs.com"]
    }
    EOF
    
    # 重新加载配置
    systemctl daemon-reload
    
    # 重启Docker
    systemctl restart docker
    

1.2、部署 MySQL

使用之前传统的方式需要:搜索并下载 MySQL 安装包,上传到 Linux 环境,编辑和配置环境,安装。而使用 Docker 安装,只需要操作命令即可

  • Docker 安装 MySQL

    docker run -d \
      --name mysql \
      -p 3306:3306 \
      -e TZ=Asia/Shanghai \
      -e MYSQL_ROOT_PASSWORD=123 \
      mysql
    

    image-20231005190900318

    这种安装方式不用考虑运行的操作系统环境,不仅仅在 CentOS,在 Ubuntu、masOs甚至是装了WSL的Windoes下,都可以使用这条命令来安装 MySQL

    不同操作系统下安装包、运行环境都是不相同的,如果是手动安装,则必须解决安装不同、环境不同、配置不同的问题,而使用 Docker 这些不需要去考虑,Docker 会自动搜索并下载 MySQL(下载的不是安装包而是镜像)

  • 问题

    Docker 会根据命令中的镜像名称来自动搜索并下载镜像,是从哪里搜索和下载,又是谁制作的镜像?

    Docker 官方提供了一个专门管理、存储镜像的网站,并对外开放了镜像上传、下载的权利:https://hub.docker.xom

    • 镜像的两种来源
      • 基于官方基础镜像自己制作
      • 直接去 DockerRegistry(镜像仓库) 去下载

Docker 本身包含一个后台服务,可以利用 Docker 命令告诉 Docker 服务,帮助我们快速部署指定的引用,Docker 服务部署应用时,首先要去搜索并下载对应的镜像,然后根据镜像创建并允许容器,应用就部署完成了

1.3、命令解读

docker run -d \
  --name mysql \
  -p 3306:3306 \
  -e TZ=Asia/Shanghai \
  -e MYSQL_ROOT_PASSWORD=123 \
  mysql
  • docker run -d:创建并运行一个容器,-d 则是让容器以后台进程运行
  • --name mysql:给容器起的一个名字(任意起)
  • -p 3306:3306:端口映射
    • 容器是隔离环境,外界不可访问,但是可以将宿主机端口映射容器内到端口,当访问宿主机指定端口是,就是在访问容器内的端口了
    • 格式:宿主机端口:容器内端口
  • -e TZ=Asia/Shanghai:配置容器内进程运行时的一些参数
  • Mysql:设置镜像名称,Docker 会根据这个名字搜索并下载镜像
    • 格式:Repository:Tag,镜像名:版本号
    • 在未指定版本号的情况下,默认是最新版本

镜像名称不是随意的,而是要到镜像仓库中寻找,镜像运行时的卑职也不是随意的,需要参考镜像的帮助文档都可以的 DockerHub 类似网站寻找到

2.Docker 基础

Docker 官方文档:https://docs.docker.com/

2.1、常见命令介绍

image-20231005192056640

  • 命令别名

    给常用 Docker 命令起别名方便访问

    # 修改/root/.bashrc文件
    vi /root/.bashrc
    内容如下:
    # .bashrc
    
    # User specific aliases and functions
    
    alias rm='rm -i'
    alias cp='cp -i'
    alias mv='mv -i'
    alias dis='docker images'
    
    # Source global definitions
    if [ -f /etc/bashrc ]; then
            . /etc/bashrc
    fi
    

    执行命令使别名生效

    source /root/.bashrc
    

2.2、数据卷

容器是隔离环境,容器内程序的文件、配置、运行时产生的容器都在容器内部,读写容器内的文件非常不方便

  • 问题
    • 如果要升级 MySQL 版本,需要销毁旧容器,那么数据是否跟着销毁了
    • MySQL、Nginx 容器运行后,如果要修改其中的某些配置该如何做
    • 如果想让 Nginx 代理静态资源怎么做

容器提供程序的运行环境,但是程序运行产生的数据、程序运行依赖的配置都应该与容器解耦

  • 数据卷概述

    数据卷是一个虚拟目录,是容器内目录与宿主机目录之间映射的桥梁

    • 以 Nginx 为例,我们知道 Nginx 中两个关键的目录
      • html:放置静态资源
      • conf:放置配置文件

    利用数据卷将两个目录与宿主机目录关联方便操作

    image-20231005193719734

  • 数据卷命令

    image-20231005193957823

    容器与数据卷的挂载要在创建容器时配置,对于创建好的容器,是不能设置数据卷的,而且创建容器的过程中,数据卷会自动创建

    • 通过挂载 nginx 的 html 目录来作为演示

      • 创建容器并指定数据卷【通过 -v 参数来指定数据卷】
      docker run -d --name nginx -p 80:80 -v html:/usr/share/nginx/html nginx
      
      • 查看数据卷
      docker volume ls
      

      image-20231005200931408

      • 查看数据卷详情
      docker volume inspect static
      

      image-20231005201010276

      • 查看 /var/lib/docker/volumes/static/_data 目录【与 nginx 的 html 目录一样】

        image-20231005201213700

      • 可以进行任意修改 index.html

      • 通过命令进入容器内部,查看 nginx 中的 index.html 是否有对应变化

        docker exec -it nginx bah
        

    每一个不同的镜像,在创建容器后内部有哪些目录可以挂载,可以参考相关网站进行查看

2.3、镜像

一直在使用别人的镜像,如果要部署一个 Java 项目,把它打包为一个镜像该如何做

  • 镜像结构

    镜像之所以可以快速跨操作系统部署应用而忽略其运行环境、配置,就是因为镜像中包含了程序运行需要的系统的函数库、环境、配置、依赖。因此,自定义镜像本质就是依次准备好程序的基础环境、依赖、应用本身、运行配置等文件,并且打包而成

    • 打包镜像步骤
      • 准备 Linux 运行环境(java项目并不需要完整的操作系统,仅仅是基础运行环境即可)
      • 安装并配置 JDK
      • 拷贝 jar 包
      • 配置启动脚本

    上述步骤中的每一次操作都是在生产一些文件(系统运行环境、函数库、配置最终都是磁盘文件),所以镜像就是一堆文件的集合。

    镜像文件不是随意堆放的,而是按照操作的步骤分层叠加而成,每一层形成的文件都会单独打包并标记一个唯一 id,成为 Layer(层) ,这样如果我们构建时用到某些层其他人已经只做过,就可以直接拷贝使用,而不用重复制作

  • 举例说明

    第一部中需要的 Linux 运行环境,通用性很强,所以 Docker 官方制作了这样的只包含 Linux 运行环境的镜像,在制作 java 镜像是,就无需重复制作,直接使用 Docker 官方提供的 CentOS 或者 Ubuntu 镜像作为基础镜像,然后再搭建其他层即可,

    image-20231005205802941

  • Dockerfile

    由于制作镜像的过程中,需要逐层处理和打包,比较复杂,所以 Docker 就提供了自动打包镜像的功能,只需要将打包的过程,每一层要做的事情用固定的语法写下来,交给 Docker 去执行即可。而这种记录镜像结构的文件就成为 Dockerfile,其对应的语法可以参考官方文档:https://docs.docker.com/engine/reference/builder/

    • 语法比较多,比较常用指令

    image-20231005210316234

    • 例如基于 Ubuntu 镜像来构建一个 Java 应用

      # 指定基础镜像
      FROM ubuntu:16.04
      # 配置环境变量,JDK的安装目录、容器内时区
      ENV JAVA_DIR=/usr/local
      ENV TZ=Asia/Shanghai
      # 拷贝jdk和java项目的包
      COPY ./jdk8.tar.gz $JAVA_DIR/
      COPY ./docker-demo.jar /tmp/app.jar
      # 设定时区
      RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
      # 安装JDK
      RUN cd $JAVA_DIR \
       && tar -xf ./jdk8.tar.gz \
       && mv ./jdk1.8.0_144 ./java8
      # 配置环境变量
      ENV JAVA_HOME=$JAVA_DIR/java8
      ENV PATH=$PATH:$JAVA_HOME/bin
      # 指定项目监听的端口
      EXPOSE 8080
      # 入口,java项目的启动命令
      ENTRYPOINT ["java", "-jar", "/app.jar"]
      
    • 问题

      之后会有很多的 Java 项目需要打包为镜像,它们都需要 Linux 系统环境、JDK 环境这两层,只有上面的部分层不同,如果每次制作 java 镜像都重复制作前两层镜像,会特别麻烦。所以,就有提供了基础的系统价 JDK 环境,在此基础上制作 java 镜像,就可以省去 JDK 的配置

      # 基础镜像
      FROM openjdk:11.0-jre-buster
      # 设定时区
      ENV TZ=Asia/Shanghai
      RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
      # 拷贝jar包
      COPY docker-demo.jar /app.jar
      # 入口
      ENTRYPOINT ["java", "-jar", "/app.jar"]
      
  • 构建进行

    当 Dockerfile 文件写好之后,就可以利用命令来构建镜像

    • 准备打包好的 Java 项目 jar 包和对应的 Dockerfile

      image-20231005211503989

    • 将 jar 以及 Dcokerfile 拷贝到 Linux 服务器当中

      # 进入镜像目录
      cd /root/demo
      # 开始构建
      docker build -t docker-demo:1.0 .
      

      image-20231005211546115

      • docker build :构建一个 docker 镜像
      • -t docker-demo:1.0:-t 指定镜像的名称【repository:tag】
      • .:最后的点指构建时 Dockerfile 所在路径

      image-20231005212354725

      • 查看镜像列表
      # 查看镜像列表:
      docker images
      # 结果
      REPOSITORY    TAG       IMAGE ID       CREATED          SIZE
      docker-demo   1.0       d6ab0b9e64b9   27 minutes ago   327MB
      nginx         latest    605c77e624dd   16 months ago    141MB
      mysql         latest    3218b38490ce   17 months ago    516MB
      
      • 运行该镜像
      # 1.创建并运行容器
      docker run -d --name dd -p 8090:8090 docker-demo:1.0
      # 2.查看容器
      dps
      # 结果
      CONTAINER ID   IMAGE             PORTS                                                  STATUS         NAMES
      78a000447b49   docker-demo:1.0   0.0.0.0:8080->8080/tcp, :::8090->8090/tcp              Up 2 seconds   dd
      f63cfead8502   mysql             0.0.0.0:3306->3306/tcp, :::3306->3306/tcp, 33060/tcp   Up 2 hours     mysql
      
      # 3.访问
      curl localhost:8080/hello/count
      # 结果:
      <h5>欢迎访问黑马商城, 这是您第1次访问<h5>
      

2.4、网络

  • 问题

    Java 项目往往需要访问其它各种中间件,例如 MySQL、Redis等,但是目前容器之间是无法互相访问的

  • 查看 MySQL 容器详细信息【重点关注网络 IP 地址】

    # 1.用基本命令,寻找Networks.bridge.IPAddress属性
    docker inspect mysql
    # 也可以使用format过滤结果
    docker inspect --format='' mysql
    # 得到IP地址如下:
    172.17.0.2
    
    # 2.然后通过命令进入dd容器
    docker exec -it dd bash
    
    # 3.在容器内,通过ping命令测试网络
    ping 172.17.0.2
    # 结果
    PING 172.17.0.2 (172.17.0.2) 56(84) bytes of data.
    64 bytes from 172.17.0.2: icmp_seq=1 ttl=64 time=0.053 ms
    64 bytes from 172.17.0.2: icmp_seq=2 ttl=64 time=0.059 ms
    64 bytes from 172.17.0.2: icmp_seq=3 ttl=64 time=0.058 ms
    

    发现可以互联没有问题,但是容器的网络 IP 其实是一个虚拟的 IP,其值并不固定与某一个容器绑定,如果在开发时写死某个 IP,而在部署的时候很可能 MySQL 容器的 IP 会发生变化造成链接失败

    借助与 docker 的网路功能来解决这个问题:https://docs.docker.com/engine/reference/commandiline/network/

  • 常见命令

    image-20231005224315436

  • 实例

    # 1.首先通过命令创建一个网络
    docker network create hmall
    
    # 2.然后查看网络
    docker network ls
    # 结果:
    NETWORK ID     NAME      DRIVER    SCOPE
    639bc44d0a87   bridge    bridge    local
    403f16ec62a2   hmall     bridge    local
    0dc0f72a0fbb   host      host      local
    cd8d3e8df47b   none      null      local
    # 其中,除了hmall以外,其它都是默认的网络
    
    # 3.让dd和mysql都加入该网络,注意,在加入网络时可以通过--alias给容器起别名
    # 这样该网络内的其它容器可以用别名互相访问!
    # 3.1.mysql容器,指定别名为db,另外每一个容器都有一个别名是容器名
    docker network connect hmall mysql --alias db
    # 3.2.dd容器,也就是我们的java项目
    docker network connect hmall dd
    
    # 4.进入dd容器,尝试利用别名访问db
    # 4.1.进入容器
    docker exec -it dd bash
    # 4.2.用db别名访问
    ping db
    # 结果
    PING db (172.18.0.2) 56(84) bytes of data.
    64 bytes from mysql.hmall (172.18.0.2): icmp_seq=1 ttl=64 time=0.070 ms
    64 bytes from mysql.hmall (172.18.0.2): icmp_seq=2 ttl=64 time=0.056 ms
    # 4.3.用容器名访问
    ping mysql
    # 结果:
    PING mysql (172.18.0.2) 56(84) bytes of data.
    64 bytes from mysql.hmall (172.18.0.2): icmp_seq=1 ttl=64 time=0.044 ms
    64 bytes from mysql.hmall (172.18.0.2): icmp_seq=2 ttl=64 time=0.054 ms
    

在自定义网络中,可以给容器起多个别名,默认的别名是容器名本身。在同一个自定义网络中的容器,可以通过别名互相访问

3.项目部署

  • 项目说明

    • hall:商城的后端代码
    • hall-portal:商城用户端的前端代码
    • hall-admin:商城管理端的前端代码
  • 部署的容器及端口

    image-20231005224840173

3.1、部署 Java 项目

  • 将项目进行打包

    image-20231006102619651

  • 将 hm-service.jar 和 Dockerfile 上传到服务器并部署项目

    # 1.构建项目镜像,不指定tag,则默认为latest
    docker build -t hmall .
    
    # 2.查看镜像
    docker images
    # 结果
    REPOSITORY    TAG       IMAGE ID       CREATED          SIZE
    hmall         latest    0bb07b2c34b9   43 seconds ago   362MB
    docker-demo   1.0       49743484da68   24 hours ago     327MB
    nginx         latest    605c77e624dd   16 months ago    141MB
    mysql         latest    3218b38490ce   17 months ago    516MB
    
    # 3.创建并运行容器,并通过--network将其加入hmall网络,这样才能通过容器名访问mysql
    docker run -d --name hmall --network hmall -p 8080:8080 hmall
    

    测试,通过浏览器进行访问:8080/search/list

3.2、部署前端

  • 项目上传

    image-20231006103118830

  • 创建 nginx 容器并完成两个挂载

    docker run -d \
      --name nginx \
      -p 18080:18080 \
      -p 18081:18081 \
      -v /root/nginx/html:/usr/share/nginx/html \
      -v /root/nginx/nginx.conf:/etc/nginx/nginx.conf \
      --network hmall \
      nginx
    

3.3、DockerCompose

可以帮助实现多个相互关联的 Docker 容器的快速部署,它允许用户通过一个单独的 docker-compose.yml 末班文件来定义一组相关联的应用容器

  • 基本用法

    docker-compose.yml:https://docs.docker.com/compose/compose-file/compose-file-v3/

    docker-compose 文件中可以定义多个相互关联的应用容器,每一个应用容器被称为一个服务。由于服务就是在定义某个应用的运行时参数,因此与 docker run 参数项次

  • 举例说明

    用 docker run 部署 MySQL

    docker run -d \
      --name mysql \
      -p 3306:3306 \
      -e TZ=Asia/Shanghai \
      -e MYSQL_ROOT_PASSWORD=123 \
      -v ./mysql/data:/var/lib/mysql \
      -v ./mysql/conf:/etc/mysql/conf.d \
      -v ./mysql/init:/docker-entrypoint-initdb.d \
      --network hmall
      mysql
    

    用 docker-compose 文件来定义

    version: "3.8"
    
    services:
      mysql:
        image: mysql
        container_name: mysql
        ports:
          - "3306:3306"
        environment:
          TZ: Asia/Shanghai
          MYSQL_ROOT_PASSWORD: 123
        volumes:
          - "./mysql/conf:/etc/mysql/conf.d"
          - "./mysql/data:/var/lib/mysql"
        networks:
          - new
    networks:
      new:
        name: hmall
    

    参数对比

    image-20231006110201978

    当前演示项目部署文件

    version: "3.8"
    
    services:
      mysql:
        image: mysql
        container_name: mysql
        ports:
          - "3306:3306"
        environment:
          TZ: Asia/Shanghai
          MYSQL_ROOT_PASSWORD: 123
        volumes:
          - "./mysql/conf:/etc/mysql/conf.d"
          - "./mysql/data:/var/lib/mysql"
          - "./mysql/init:/docker-entrypoint-initdb.d"
        networks:
          - hm-net
      hmall:
        build: 
          context: .
          dockerfile: Dockerfile
        container_name: hmall
        ports:
          - "8080:8080"
        networks:
          - hm-net
        depends_on:
          - mysql
      nginx:
        image: nginx
        container_name: nginx
        ports:
          - "18080:18080"
          - "18081:18081"
        volumes:
          - "./nginx/nginx.conf:/etc/nginx/nginx.conf"
          - "./nginx/html:/usr/share/nginx/html"
        depends_on:
          - hmall
        networks:
          - hm-net
    networks:
      hm-net:
        name: hmall
    
  • 基础命令

    Https://docs.docker.com/compose/reference/

    • 基础语法
    docker compse [options] [command]
    

    image-20231009114608866

    • 示例
    # 1.进入root目录
    cd /root
    
    # 2.删除旧容器
    docker rm -f $(docker ps -qa)
    
    # 3.删除hmall镜像
    docker rmi hmall
    
    # 4.清空MySQL数据
    rm -rf mysql/data
    
    # 5.启动所有, -d 参数是后台启动
    docker compose up -d
    # 结果:
    [+] Building 15.5s (8/8) FINISHED
     => [internal] load build definition from Dockerfile                                    0.0s
     => => transferring dockerfile: 358B                                                    0.0s
     => [internal] load .dockerignore                                                       0.0s
     => => transferring context: 2B                                                         0.0s
     => [internal] load metadata for docker.io/library/openjdk:11.0-jre-buster             15.4s
     => [1/3] FROM docker.io/library/openjdk:11.0-jre-buster@sha256:3546a17e6fb4ff4fa681c3  0.0s
     => [internal] load build context                                                       0.0s
     => => transferring context: 98B                                                        0.0s
     => CACHED [2/3] RUN ln -snf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && echo   0.0s
     => CACHED [3/3] COPY hm-service.jar /app.jar                                           0.0s
     => exporting to image                                                                  0.0s
     => => exporting layers                                                                 0.0s
     => => writing image sha256:32eebee16acde22550232f2eb80c69d2ce813ed099640e4cfed2193f71  0.0s
     => => naming to docker.io/library/root-hmall                                           0.0s
    [+] Running 4/4
     ✔ Network hmall    Created                                                             0.2s
     ✔ Container mysql  Started                                                             0.5s
     ✔ Container hmall  Started                                                             0.9s
     ✔ Container nginx  Started                                                             1.5s
    
    # 6.查看镜像
    docker compose images
    # 结果
    CONTAINER           REPOSITORY          TAG                 IMAGE ID            SIZE
    hmall               root-hmall          latest              32eebee16acd        362MB
    mysql               mysql               latest              3218b38490ce        516MB
    nginx               nginx               latest              605c77e624dd        141MB
    
    # 7.查看容器
    docker compose ps
    # 结果
    NAME                IMAGE               COMMAND                  SERVICE             CREATED             STATUS              PORTS
    hmall               root-hmall          "java -jar /app.jar"     hmall               54 seconds ago      Up 52 seconds       0.0.0.0:8080->8080/tcp, :::8080->8080/tcp
    mysql               mysql               "docker-entrypoint.s…"   mysql               54 seconds ago      Up 53 seconds       0.0.0.0:3306->3306/tcp, :::3306->3306/tcp, 33060/tcp
    nginx               nginx               "/docker-entrypoint.…"   nginx               54 seconds ago      Up 52 seconds       80/tcp, 0.0.0.0:18080-18081->18080-18081/tcp, :::18080-18081->18080-18081/tcp
    

results matching ""

    No results matching ""