Docker的基本使用

Docker 为什么出现

一次镜像,处处运行

在开发、测试和运维的工作中,总是会遇到各种环境问题,导致项目无法正常运行,阻碍工作进度。

通过 docker 的==容器虚拟化技术==,开发人员开发好之后,将程序和相关环境(mysql,jdk 等)打包成镜像,而测试和运维人员只需要拉去镜像即可。实现==镜像既应用==。这就实现了跨平台、跨服务器。只需要一次配置好环境,换到别的机子上就可以一键部署好,大大简化了操作。

所谓镜像可以理解为一个绿色免安装的包,下载下来就可以直接运行

下载与安装

下载:到docker 官网。对于 CentOS 的系统需要配置 yum,对于 Ubuntu 的需要配置 apt

  • CentOS

    # 安装yum工具
    yum install -y yum-utils
    #安装成功后,执行命令,配置Docker的yum源:
    yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
    # 使用yum安装
    yum install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
    
  • Ubuntu

    # Add Docker's official GPG key:
    sudo apt-get update
    sudo apt-get install ca-certificates curl
    sudo install -m 0755 -d /etc/apt/keyrings
    sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
    sudo chmod a+r /etc/apt/keyrings/docker.asc
    
    # Add the repository to Apt sources:
    echo \
      "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu \
      $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
      sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
    sudo apt-get update
    # To install the latest version
    sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
    # Verify that the Docker Engine installation is successful
    sudo docker run hello-world
    

配置 docker 的镜像:镜像可以在:登录阿里云–产品–容器–容器镜像服务–镜像加速器

# 创建目录
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

快速入门

docker run -d \
  --name mysql \
  -p 3306:3306 \
  -e TZ=Asia/Shanghai \
  -e MYSQL_ROOT_PASSWORD=123 \
  mysql:5.7
####################################
# docker run :创建并运行一个容器,-d 是让容器在后台运行
# --name mysql :给容器起个名字,必须唯一
# -p 3306:3306 :设置端口映射
# -e KEY=VALUE :是设置环境变量
# mysql:5.7  指定运行的镜像的名字
#######################################
# 镜像命名规范:[repository]:[tag]
### repository就是镜像名
### tag是镜像的版本
### 在没有指定tag时,默认是latest,代表最新版本的镜像

什么是端口映射

-p 宿主机端口(服务器的端口):容器内端口

容器是一个完全隔离的状态,无法从外部直接连接容器内部的 3306,也就是不能直接连接容器内部的 MySQL。

如果我们创建连个个 MySQL 的容器,就会发现连个映射关系:3307->33063306->3306

root@hcss-ecs-1b9f:~# docker ps
CONTAINER ID   IMAGE       COMMAND                  CREATED         STATUS         PORTS                                                  NAMES
3119c3ec4cbb   mysql:5.7   "docker-entrypoint.s…"   9 seconds ago   Up 7 seconds   33060/tcp, 0.0.0.0:3307->3306/tcp, :::3307->3306/tcp   mysql2
7fb520c997ee   mysql:5.7   "docker-entrypoint.s…"   2 hours ago     Up 2 hours     0.0.0.0:3306->3306/tcp, :::3306->3306/tcp, 33060/tcp   mysql

常见命令

docker inspect 容器名:查看容器详情,如数据卷的挂载等

一个 docker 使用的正常流程:下载 Nginx 镜像

  • docker hub上查看 Nginx 的版本

  • 下载最新的 Nginx 版本:docker pull nginx

  • 查看是否下载成功:docker images

  • 想把镜像保存到本地,使用docker save,但不是后面的参数怎么写,使用docker save --help

  • 将镜像保存到本地:docker save -o 1.tar nginx:latest

    root@hcss-ecs-1b9f:~# docker save -o 1.tar nginx:latest
    root@hcss-ecs-1b9f:~# ll
    total 142588
    drwx------  7 root root      4096 Feb 29 12:17 ./
    drwxr-xr-x 24 root root      4096 Feb 28 20:13 ../
    -rw-------  1 root root 145902080 Feb 29 12:17 1.tar #这
    drwx------  3 root root      4096 Jan 12 13:45 .ansible/
    -rw-r--r--  1 root root      1459 Feb 28 22:25 .bash_history
    -rw-r--r--  1 root root      3106 Oct 15  2021 .bashrc
    drwx------  3 root root      4096 Jan 12 13:51 .cache/
    -rw-------  1 root root         0 Jul 13  2023 .history
    -rwxr-xr-x  1 root root     15353 Jan 12 13:47 HSSInstall*
    -rw-r--r--  1 root root     35331 Jan  4 17:21 install.sh
    drwxr-xr-x  2 root root      4096 Jan 12 13:51 .pip/
    -rw-r--r--  1 root root       161 Jul  9  2019 .profile
    drwx------  3 root root      4096 Jan 12 13:43 snap/
    drwx------  2 root root      4096 Feb 26 22:46 .ssh/
    -rw-------  1 root root       880 Feb 29 11:12 .viminfo
    -rw-r--r--  1 root root       246 Jan 12 13:56 .wget-hsts
    -rw-------  1 root root        58 Jan 12 13:50 .Xauthority
    root@hcss-ecs-1b9f:~# pwd
    /root
    
  • 删除 NGINX 镜像docker rmi nginx:latest

  • 加载本地镜像docker load -i 1.tar -q

    • -i 1.tar:本地镜像的名字
    • -q:加载的时候不会打印日志(quiet)
  • 创建并运行一个 Nginx 容器:docker run -d --name nginx -p 80:80 nginx:latest

  • 查看容器是否运行:docker ps

    root@hcss-ecs-1b9f:~# docker ps
    CONTAINER ID   IMAGE          COMMAND                  CREATED             STATUS             PORTS                                                  NAMES
    f4a55fdafb94   nginx:latest   "/docker-entrypoint.…"   10 seconds ago      Up 9 seconds       0.0.0.0:80->80/tcp, :::80->80/tcp                      nginx
    7fb520c997ee   mysql:5.7      "docker-entrypoint.s…"   About an hour ago   Up About an hour   0.0.0.0:3306->3306/tcp, :::3306->3306/tcp, 33060/tcp   mysql
    
  • 可以对输出的内容进行格式化:docker ps --format "table {{.ID}}\t{{.Image}}\t{{.Ports}}\t{{.Status}}\t{{.Names}}"

    root@hcss-ecs-1b9f:~# docker ps --format "table {{.ID}}\t{{.Image}}\t{{.Ports}}\t{{.Status}}\t{{.Names}}"
    CONTAINER ID   IMAGE          PORTS                                                  STATUS         NAMES
    f4a55fdafb94   nginx:latest   0.0.0.0:80->80/tcp, :::80->80/tcp                      Up 3 minutes   nginx
    7fb520c997ee   mysql:5.7      0.0.0.0:3306->3306/tcp, :::3306->3306/tcp, 33060/tcp   Up 2 hours     mysql
    
  • 停掉 NGINX:docker stop nginx

    root@hcss-ecs-1b9f:~# docker stop nginx
    nginx
    root@hcss-ecs-1b9f:~# docker ps --format "table {{.ID}}\t{{.Image}}\t{{.Status}}\t{{.Names}}"
    CONTAINER ID   IMAGE       STATUS       NAMES
    7fb520c997ee   mysql:5.7   Up 2 hours   mysql
    
  • 如果我们想查看所有容器docker ps --format "xxxx" -a

    root@hcss-ecs-1b9f:~# docker ps --format "table {{.ID}}\t{{.Image}}\t{{.Status}}\t{{.Names}}" -a
    CONTAINER ID   IMAGE          STATUS                      NAMES
    f4a55fdafb94   nginx:latest   Exited (0) 3 minutes ago    nginx
    0d59c7149c7d   mysql:5.7      Exited (1) 14 minutes ago   mysql2
    7fb520c997ee   mysql:5.7      Up 2 hours                  mysql
    
  • 再次启动 NGINX:docker start nginx

    root@hcss-ecs-1b9f:~# docker start nginx
    nginx
    root@hcss-ecs-1b9f:~# docker ps --format "table {{.ID}}\t{{.Image}}\t{{.Status}}\t{{.Names}}"
    CONTAINER ID   IMAGE          STATUS          NAMES
    f4a55fdafb94   nginx:latest   Up 17 seconds   nginx
    7fb520c997ee   mysql:5.7      Up 2 hours      mysql
    
  • 查看 NGINX 的运行日志:docker logs nginx

    root@hcss-ecs-1b9f:~# docker logs nginx
    /docker-entrypoint.sh: /docker-entrypoint.d/ is not empty, will attempt to perform configuration
    ......
    /docker-entrypoint.sh: Configuration complete; ready for start up
    2024/02/29 05:00:47 [notice] 1#1: using the "epoll" event method
    ......
    2024/02/29 05:12:22 [notice] 1#1: start worker process 25
    root@hcss-ecs-1b9f:~#
    
  • 查看 Nginx 的日志:持续输出:docker logs -f nginx。停止:ctl+c

  • 进入容器内部:docker exec

    root@hcss-ecs-1b9f:~# docker exec --help
    
    Usage:  docker exec [OPTIONS] CONTAINER COMMAND [ARG...]
    
    Execute a command in a running container
    
    Aliases:
      docker container exec, docker exec
    
    Options:
      -d, --detach               Detached mode: run command in the background
          --detach-keys string   Override the key sequence for detaching a container
      -e, --env list             Set environment variables
          --env-file list        Read in a file of environment variables
      -i, --interactive          Keep STDIN open even if not attached
          --privileged           Give extended privileges to the command
      -t, --tty                  Allocate a pseudo-TTY
      -u, --user string          Username or UID (format: "<name|uid>[:<group|gid>]")
      -w, --workdir string       Working directory inside the container
    

    在 Linux 中,STDIN是标准的输入流,通常对应终端的键盘

    如果对 Linux 的 TTY 比较熟悉的话,对于这个选项就比较了解了。我们可以把它理解为 Linux 的终端程序,所以-t选项就可以理解为为容器分配一个伪 tty 终端并绑定到容器的标准输入上,之后用户就可以通过终端来控制容器了。

    一般-t都是与-i一起出现的,也就是-it

    具体课参考这篇博客

    root@hcss-ecs-1b9f:~# docker exec -it nginx bash
    root@f4a55fdafb94:/#
    

    进入nginx这个容器,使用bash的命令行格式。

    执行完之后:root@hcss-ecs-1b9f变为root@f4a55fdafb94。说明已经进入到容器内部。而f4a55fdafb94这串数字是 Nginx 的容器 ID

    容器内部模拟了一个真实的文件系统(linux)

    root@f4a55fdafb94:/# ls
    bin   dev           docker-entrypoint.sh  home  lib64  mnt  proc  run   srv  tmp  var
    boot  docker-entrypoint.d  etc             lib   media  opt  root  sbin  sys  usr
    root@f4a55fdafb94:/#
    
  • 退出容器:exit

    root@f4a55fdafb94:/# exit
    exit
    root@hcss-ecs-1b9f:~#
    
  • 也可以在容器中直接使用对应程序,以 mysql 为例

    root@hcss-ecs-1b9f:~# docker exec -it mysql bash
    root@7fb520c997ee:/# mysql -uroot -p
    Enter password: ## 数据库的密码是在下载mysql的时候配置环境(-e)的时候设置的
    Welcome to the MySQL monitor.  Commands end with ; or \g.
    Your MySQL connection id is 5
    Server version: 5.7.36 MySQL Community Server (GPL)
    
    Copyright (c) 2000, 2021, Oracle and/or its affiliates.
    
    Oracle is a registered trademark of Oracle Corporation and/or its
    affiliates. Other names may be trademarks of their respective
    owners.
    
    Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
    mysql> show databases;
    +--------------------+
    | Database           |
    +--------------------+
    | information_schema |
    | mysql              |
    | performance_schema |
    | sys                |
    +--------------------+
    4 rows in set (0.00 sec)
    mysql> exit
    Bye
    root@7fb520c997ee:/# exit
    exit
    root@hcss-ecs-1b9f:~#
    
  • 删除容器:

    • 先停掉容器docker stop nginx,再删除docker rm nginx

      root@hcss-ecs-1b9f:~# docker rm nginx
      Error response from daemon: cannot remove container "/nginx": container is running: stop the container before removing or force remove
      root@hcss-ecs-1b9f:~# docker stop nginx
      nginx
      root@hcss-ecs-1b9f:~# docker rm nginx
      nginx
      root@hcss-ecs-1b9f:~#
      
    • 强制删除docker rm mysql2 -f

      root@hcss-ecs-1b9f:~# docker rm mysql2
      Error response from daemon: cannot remove container "/mysql2": container is running: stop the container before removing or force remove
      root@hcss-ecs-1b9f:~# docker rm mysql2 -f
      mysql2
      
  • 别名:简化命令。需要在~/.bashrc这个文件下面配置,配置之后需要启用配置文件source ~/.bashrc

    # 编辑配置文件
    root@hcss-ecs-1b9f:~# vim ~/.bashrc
    
    alias dpsf1='docker ps --format "table {{.ID}}\t{{.Image}}\t{{.Ports}}\t{{.Status}}\t{{.Names}}"'
    alias dpsf1a='docker ps --format "table {{.ID}}\t{{.Image}}\t{{.Ports}}\t{{.Status}}\t{{.Names}}" -a'
    alias dpsf2='docker ps --format "table {{.ID}}\t{{.Image}}\t{{.Status}}\t{{.Names}}"'
    alias dpsf2a='docker ps --format "table {{.ID}}\t{{.Image}}\t{{.Status}}\t{{.Names}}" -a'
    
    # 启用配置文件
    root@hcss-ecs-1b9f:~# source ~/.bashrc
    
    root@hcss-ecs-1b9f:~# dpsf2
    CONTAINER ID   IMAGE       STATUS       NAMES
    7fb520c997ee   mysql:5.7   Up 3 hours   mysql
    

数据的挂载

为什么

root@hcss-ecs-1b9f:~# docker exec -it nginx bash
root@d9d0d3603b32:/# cd /usr/share/nginx/html
root@d9d0d3603b32:/usr/share/nginx/html# ls
50x.html  index.html
root@d9d0d3603b32:/usr/share/nginx/html# vi index.html
bash: vi: command not found

我们希望修改 nginx 的静态资源,但是进入到容器内部,发现没有 vi 命令。这是因为容器只配置了应用运行的最小运行资源。许多类似 vi 的命令都没有,使得修改和上次文件显得特别困难。这个时候我们就需要利用数据卷来挂载。

数据卷

挂载的原理

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

如何挂载

在创建容器时只需要执行如下命令:

docker run -d --name nginx -p80:80 -v 数据卷名字:容器内目录 nginx
# 数据卷的挂载只能在创建容器时挂载,所有需要先删掉容器
root@hcss-ecs-1b9f:~# docker rm -f nginx
nginx

#在执行docker run命令时,使用 -v 数据卷:容器内目录 可以完成数据卷挂载
root@hcss-ecs-1b9f:~# docker run -d --name nginx -p80:80 -v html:/usr/share/nginx/html nginx
82538b0c5ea99d79b330e8fc5661e8919ef3e7f0b2fd32b50e07a8c1fc089a1d

# 查看所有数据卷
root@hcss-ecs-1b9f:~# docker volume ls
DRIVER    VOLUME NAME
local     a505a328c817d28f3cfff9def729f0fe463323df23261eb494461b2fdc65cda5
local     html

# 查看某个数据卷的详情
root@hcss-ecs-1b9f:~# docker volume inspect html
[
    {
        "CreatedAt": "2024-03-06T11:36:47+08:00",
        "Driver": "local",
        "Labels": null,
        "Mountpoint": "/var/lib/docker/volumes/html/_data",
        "Name": "html",
        "Options": null,
        "Scope": "local"
    }
]

最终实现的效果是:宿主机/var/lib/docker/volumes/html/_data 和容器/usr/share/nginx/html 两个目录下各有一份文件

数据卷的操作

docker volume create:创建数据卷

docker volume ls:查看所有数据卷

docker volume rm:删除指定数据卷

docker volume inspect:查看某个数据卷的详情

docker volume prune:清除数据卷

本地目录挂载

如果我们在创建容器的时候没有指定数据卷的挂载,docker 会自动创建一个匿名卷

root@hcss-ecs-1b9f:~# docker volume ls
DRIVER    VOLUME NAME
local     a505a328c817d28f3cfff9def729f0fe463323df23261eb494461b2fdc65cda5
local     html

挂载信息如下:

root@hcss-ecs-1b9f:~# docker inspect mysql

"Mounts": [
    {
        "Type": "volume",
        "Name": "a505a328c8...fdc65cda5",
        "Source": "/var/lib/docker/volumes/a505a328c817...dc65cda5/_data",
        "Destination": "/var/lib/mysql",
        "Driver": "local",
        "Mode": "",
        "RW": true,
        "Propagation": ""
     }
],

挂载的是容器内的/var/lib/mysql目录。这个目录是 mysql 的数据存储目录。

为什么 mysql 要把他的数据存储目录挂载到宿主机呢?因为如果不挂载,容器的体积越来越大,未来容器迁移会很麻烦,为了数据的解耦,这个做法是有必要的

为什么不能用匿名卷:

  • 如果容器升级后需要删除容器,当我们新建容器的时候,再采用匿名卷的方式,就没有产生数据的迁移
  • 名字太长,今天的许多操作都不方便

新方式:挂载到任意目录下

案例:基于宿主机目录实现 MySQL 数据目录、配置文件、初始化脚本的挂载(不知道目录在哪,可以查阅官方镜像文档

  • 挂载/root/mysql/data 到容器内的/var/lib/mysql 目录
  • 挂载/root/mysql/init 到容器内的/docker-entrypoint-initdb.d 目录,携带课前资料准备的 SQL 脚本
  • 挂载/root/mysql/conf 到容器内的/etc/mysql/conf.d 目录,携带课前资料准备的配置文件

在执行 docker run 命令时,使用 -v 本地目录 : 容器内目录 可以完成本地目录挂载

本地目录必须以“/”或 “./“ 开头,如果直接以名称开头,会被识别为数据卷而非本地目录

  • -v mysql : /var/lib/mysql 会被识别为一个数据卷叫 mysql
  • -v ./mysql : /var/lib/mysql 会被识别为当前目录下的 mysql 目录

在宿主机创建目录之后,再执行以下命令

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

执行的时候遇到的问题:

  • 首先,自己之前下载的不是最新版本的,是 mysql5.7 的,导致在执行/root/mysql/init 中的初始化脚本的时候,遇到了错误。conf 中的配置文件执行了,但是 sql 脚本没有执行

  • 于是我下载最新版本的,把原来 5.7 的镜像卸载掉。结果运行 docker run 之后没有启动。查看日志报了一下错误:

    Upgrade after a crash is not supported. This redo log was created with MySQL 5.7.36. Please follow the instructions at http://dev.mysql.com/doc/refman/8.0/en/upgrading.html
    

    原因是上一次 docker run 的时候,data 文件夹里面已经生成了一些数据。是个 5.7 版本相关的。这样就和我最新版本的镜像相冲突。

自定义镜像与 dockerfile

以上都是下载别人制作好的镜像,但是如果我们要项目部署的时候,我们也要报项目打包,制成镜像。

镜像就是包含了应用程序、程序运行的系统函数库、运行配置等文件的文件包。构建镜像的过程其实就是把上述文件打包的过程。

构建一个 Java 镜像的步骤:

  • 准备一个 Linux 运行环境
  • 安装 JRE 并配置环境变量
  • 拷贝 Jar 包
  • 编写运行脚本

镜像的结构:

这样分层打包的好处:

  • 可以共享一些基础的层。比如对于所有的 Ubuntu 的操作系统,我们都需要构建 Ubantu 的基础镜像,我们需要把一些基础的函数库挑出来,这是一个非常费时费力的操作。可如果我们挑出来之后,打包成镜像,上传到公共仓库,这样下次就不需要再挑选函数了。

  • 与此同时,下载速度也会大大提升。因为 docker 在下载镜像的时候,会先检查本地是否存在同样的镜像,如果有,就不会下载

    root@hcss-ecs-1b9f:~# docker pull redis
    Using default tag: latest
    latest: Pulling from library/redis
    a2abf6c4d29d: Already exists  ## 这句就在检查本地仓库
    c7a4e4382001: Pull complete
    4044b9ba67c9: Pull complete
    c8388a79482f: Pull complete
    413c8bb60be2: Pull complete
    1abfd3011519: Pull complete
    Digest: sha256:db485f2e245b5b3329fdc7eff4eb00f913e09d8feb9ca720788059fdc2ed8339
    Status: Downloaded newer image for redis:latest
    docker.io/library/redis:latest
    root@hcss-ecs-1b9f:~#
    

Dockerfile

Dockerfile 就是一个文本文件,其中包含一个个的指令(Instruction),用指令来说明要执行什么操作来构建镜像。将来 Docker 可以根据 Dockerfile 帮我们构建镜像。常见指令如下:

指令 说明 示例
FROM 指定基础镜像 FROM centos:6
ENV 设置环境变量,可在后面指令使用 ENV key value
COPY **拷贝本地文件到镜像的指定目录:**这些目录未必存在,但是只要写了,将来 docker 在创建镜像的时候会创建这个目录,然后把指定词镜像放在这个目录里面 COPY ./jre11.tar.gz /tmp
RUN 执行 Linux 的 shell 命令,一般是安装过程的命令。 RUN tar -zxvf /tmp/jre11.tar.gz&& EXPORTS path=/tmp/jre11:$path
EXPOSE 指定容器运行时监听的端口,是给镜像使用者看的 EXPOSE 8080
ENTRYPOINT 镜像中应用的启动命令,容器运行时调用 ENTRYPOINT java -jar xx.jar

例如,要基于 Ubuntu 镜像来构建一个 Java 应用,其 Dockerfile 内容如下:

# 指定基础镜像
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:因为COPY过来的是压缩报,需要解压安装
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"]

上述步骤很多,但是主语都是与 jdk 镜像相关的步骤,于是有人把 jdk+系统环境结合在一起,制作了一个基础镜像,如 openjdk:11.0-jre-buster。这样作就大大简化了配置。

# 基础镜像
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"]

构建镜像

root@hcss-ecs-1b9f:~/demo# docker build -t docker-demo .
  • docker build:就是构建一个 docker 镜像

  • -t docker-demo:给惊喜取名 docker-demo。格式依然是**repository:tag**的格式,不指定 tag 时,默认为 latest。如果我想指定版本就可以写:-t docker-demo:1.0

  • .:最后的点是指构建时 Dockerfile 所在路径,也就是告诉 docker 去哪里找 dockerfile 文件(告诉 docker 怎么构建)。由于我们进入了 demo 目录,所以指定的是.代表当前目录,也可以直接指定 Dockerfile 目录:

    # 直接指定Dockerfile目录
    docker build -t docker-demo:1.0 /root/demo
    

    [!NOTE]

    对于运行docker build -t docker-demo .这个命令,也必须在 dockerfile 对应的文件夹下,否则回报如下错误:

    ERROR: failed to solve: failed to read dockerfile: open Dockerfile: no such file or directory
    

    dockerfile 文件要和 docker-demo.jar 在一起,因为我们拷贝 jar 包的时候使用的是相对路径

    # 拷贝jar包
    COPY docker-demo.jar /app.jar
    

    demo 里面的文件:

    root@hcss-ecs-1b9f:~/demo# ll
    total 17292
    drwxr-xr-x 2 root root     4096 Mar  6 17:49 ./
    drwx------ 9 root root     4096 Mar  6 17:45 ../
    -rw-r--r-- 1 root root 17692387 Mar  6 17:51 docker-demo.jar
    -rw-r--r-- 1 root root      260 Mar  6 17:49 Dockerfile
    

    另外也必须叫Dockerfile。因为我们的指令(docker build -t docker-demo:1.0 /root/demo)没有指定文件名

    /app.jar这个路径是容器内的路径:

    root@hcss-ecs-1b9f:~/demo# docker exec -it dd bash
    root@887dee3ce049:/# ls
    app.jar  bin  boot  dev  etc  home  lib  lib64    media  mnt  opt  proc  root  run  sbin    srv  sys  tmp  usr  var
    
docker run -d --name dd -p 8080:8080 docker-demo

应用制定的是 8080

可以用docker logs dd查看日志,看看是否启动

网络

**默认情况下,所有容器都是以 bridge 方式连接到 Docker 的一个虚拟网桥上。**图中的/16表示前 16 位不能动,每一段最大数是 255(2^8^),也就是前两段不能动。

所有虽然个个容器是独立空间,但是可以同网桥相互访问。

但是因为 IP 地址是网桥自动分配的,不是固定 IP,不固定与某一个容器绑定。如果我们在开发时写死某个 IP,而在部署时很可能 MySQL 容器的 IP 会发生变化,连接会失败。

我们需要创建一个自定义的网络。一旦创建自定义的网络,就会形成新的网桥,生成新的网段。加入这个自定义网络的容器,就可以相互连接。加入自定义网络的容器还可以通过容器名互相访问,这样就不需要知道对方的 IP 地址,Docker 的网络操作命令如下:

命令 说明 文档地址
docker network create 创建一个网络 docker network create
docker network ls 查看所有网络 docs.docker.com
docker network rm 删除指定网络 docs.docker.com
docker network prune 清除未使用的网络 docs.docker.com
docker network connect 使指定容器连接加入某网络 docs.docker.com
docker network disconnect 使指定容器连接离开某网络 docker network disconnect
docker network inspect 查看网络详细信息 docker network inspect
# 创建一个网络
root@hcss-ecs-1b9f:~# docker network create test
6bb868db1b7acdd42d4eb0d80c7ee8a1d5f44c7047484644f1fb14de3ebeaa62
# 查看所有网络
root@hcss-ecs-1b9f:~# docker network ls
NETWORK ID     NAME      DRIVER    SCOPE
944bbb7fa383   bridge    bridge    local
614dfc283894   host      host      local
7850dabd07e4   none      null      local
6bb868db1b7a   test      bridge    local
# 使指定容器连接加入某网络 docker network connect [OPTIONS] NETWORK CONTAINER
root@hcss-ecs-1b9f:~# docker network connect test mysql
root@hcss-ecs-1b9f:~# docker inspect mysql

# 查看mysql的网络:有两个了 bridge和test
root@hcss-ecs-1b9f:~# docker inspect mysql
 "Networks": {
                "bridge": { ####notice#####
                    "IPAMConfig": null,
                    "Links": null,
                    "Aliases": null,
                    "MacAddress": "02:42:ac:11:00:02",
                    "NetworkID": "944bbb7fa383025fd566712c925ff09e676233ef6beb41b28b485e6c2e4d87cf",
                    "EndpointID": "35beba36e7644ff9ad340cbb5820c1f8695382c9cb2f5e895c39610507fa5301",
                    "Gateway": "172.17.0.1",
                    "IPAddress": "172.17.0.2",
                    "IPPrefixLen": 16,
                    "IPv6Gateway": "",
                    "GlobalIPv6Address": "",
                    "GlobalIPv6PrefixLen": 0,
                    "DriverOpts": null,
                    "DNSNames": null
                },
                "test": { ####notice#####
                    "IPAMConfig": {},
                    "Links": null,
                    "Aliases": [
                        "cf3d698e83e6"
                    ],
                    "MacAddress": "02:42:ac:12:00:02",
                    "NetworkID": "6bb868db1b7acdd42d4eb0d80c7ee8a1d5f44c7047484644f1fb14de3ebeaa62",
                    "EndpointID": "0d8c91c4d270b4a1cfe9041dd3ef756d0622d0d9addc886747f445326d2f809a",
                    "Gateway": "172.18.0.1",
                    "IPAddress": "172.18.0.2",
                    "IPPrefixLen": 16,
                    "IPv6Gateway": "",
                    "GlobalIPv6Address": "",
                    "GlobalIPv6PrefixLen": 0,
                    "DriverOpts": {},
                    "DNSNames": [
                        "mysql",
                        "cf3d698e83e6"
                    ]
                }
            }

# 创建容器的时候连接
root@hcss-ecs-1b9f:~# docker run -d --name dd -p 8080:8080 --network test docker-demo
99100c6381c8917cba470469b2645231ce2b00bed76ab34eac84ab016b0132cc

# dd 里面没有默认的bridge网桥
root@hcss-ecs-1b9f:~# docker inspect dd
            "Networks": {
                "test": {####notice#####
                    "IPAMConfig": null,
                    "Links": null,
                    "Aliases": [
                        "99100c6381c8"
                    ],
                    "MacAddress": "02:42:ac:12:00:03",
                    "NetworkID": "6bb868db1b7acdd42d4eb0d80c7ee8a1d5f44c7047484644f1fb14de3ebeaa62",
                    "EndpointID": "428acbf085ea232ea05a6537c7bb8ba5571af7b193b46118a693d51e646ef2d1",
                    "Gateway": "172.18.0.1",
                    "IPAddress": "172.18.0.3",
                    "IPPrefixLen": 16,
                    "IPv6Gateway": "",
                    "GlobalIPv6Address": "",
                    "GlobalIPv6PrefixLen": 0,
                    "DriverOpts": null,
                    "DNSNames": [
                        "dd",
                        "99100c6381c8"
                    ]
                }
            }
        }

# 进入到容器内部
root@hcss-ecs-1b9f:~# docker exec -it dd bash

# 可以直接用名字 ping test的网络
root@99100c6381c8:/# ping mysql
PING mysql (172.18.0.2) 56(84) bytes of data.
64 bytes from mysql.test (172.18.0.2): icmp_seq=1 ttl=64 time=0.211 ms
64 bytes from mysql.test (172.18.0.2): icmp_seq=2 ttl=64 time=0.091 ms
64 bytes from mysql.test (172.18.0.2): icmp_seq=3 ttl=64 time=0.085 ms
64 bytes from mysql.test (172.18.0.2): icmp_seq=4 ttl=64 time=0.091 ms
64 bytes from mysql.test (172.18.0.2): icmp_seq=5 ttl=64 time=0.084 ms
64 bytes from mysql.test (172.18.0.2): icmp_seq=6 ttl=64 time=0.096 ms
64 bytes from mysql.test (172.18.0.2): icmp_seq=7 ttl=64 time=0.085 ms
64 bytes from mysql.test (172.18.0.2): icmp_seq=8 ttl=64 time=0.080 ms
64 bytes from mysql.test (172.18.0.2): icmp_seq=9 ttl=64 time=0.100 ms
64 bytes from mysql.test (172.18.0.2): icmp_seq=10 ttl=64 time=0.092 ms
64 bytes from mysql.test (172.18.0.2): icmp_seq=11 ttl=64 time=0.086 ms
64 bytes from mysql.test (172.18.0.2): icmp_seq=12 ttl=64 time=0.075 ms
64 bytes from mysql.test (172.18.0.2): icmp_seq=13 ttl=64 time=0.081 ms
ç64 bytes from mysql.test (172.18.0.2): icmp_seq=14 ttl=64 time=0.085 ms
64 bytes from mysql.test (172.18.0.2): icmp_seq=15 ttl=64 time=0.097 ms
64 bytes from mysql.test (172.18.0.2): icmp_seq=16 ttl=64 time=0.077 ms
^C
--- mysql ping statistics ---
16 packets transmitted, 16 received, 0% packet loss, time 374ms
rtt min/avg/max/mdev = 0.075/0.094/0.211/0.033 ms

# 无法ping bridge的网络,因为dd容器里面没有bridge
root@99100c6381c8:/# ping 172.17.0.2
PING 172.17.0.2 (172.17.0.2) 56(84) bytes of data.
^C
--- 172.17.0.2 ping statistics ---
60 packets transmitted, 0 received, 100% packet loss, time 469ms

项目部署

java 项目

  1. 把项目打成 jar 包:注意在父工程打包

  2. 将 jar 包和 Dockerfile 上传至服务器

    root@hcss-ecs-1b9f:~/hmall# ll
    total 66640
    drwxr-xr-x  2 root root     4096 Mar  7 11:46 ./
    drwx------ 11 root root     4096 Mar  7 11:35 ../
    -rw-r--r--  1 root root      259 Mar  7 11:46 Dockerfile
    -rw-r--r--  1 root root 68225166 Mar  7 11:42 hm-service.jar
    
  3. 创建镜像

    root@hcss-ecs-1b9f:~/hmall# docker build -t hmall .
    [+] Building 17.6s (8/8) FINISHED                                                                           docker:default
     => [internal] load build definition from Dockerfile                                                                  0.0s
     => => transferring dockerfile: 298B                                                                                  0.0s
     => [internal] load metadata for docker.io/library/openjdk:11.0-jre-buster                                           15.5s
     => [internal] load .dockerignore                                                                                     0.0s
     => => transferring context: 2B                                                                                       0.0s
     => [1/3] FROM docker.io/library/openjdk:11.0-jre-buster@sha256:3546a17e6fb4ff4fa681c38f3f6644efd393f9bb7ed6ebbd85f0  0.0s
     => [internal] load build context                                                                                     0.6s
     => => transferring context: 68.24MB                                                                                  0.5s
     => CACHED [2/3] RUN ln -snf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && echo Asia/Shanghai > /etc/timezone   0.0s
     => [3/3] COPY hm-service.jar /app.jar                                                                                0.9s
     => exporting to image                                                                                                0.3s
     => => exporting layers                                                                                               0.2s
     => => writing image sha256:82fd88f5fd5bfa054acd6b5072e1356787a91fa618d3528d25514c78398bf965                          0.0s
     => => naming to docker.io/library/hmall                                                                              0.0s
    root@hcss-ecs-1b9f:~/hmall#
    
  4. 运行镜像

    docker run -d --name hmall -p 8080:8080 --network test hmall
    

前端项目

为了方面,前端代码是写在 Nginx 的静态资源里面的的。nginx 里面有一些配置需要我们注意:

http {
    include       mime.types;
    default_type  application/json;

    sendfile        on;

    keepalive_timeout  65;

    server {
        listen       18080;
        # 指定前端项目所在的位置:这里需要进行容器的挂载,报静态资源挂载到容器内
        location / {
            root /usr/share/nginx/html/hmall-portal;
        }

        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }
        location /api {
            rewrite /api/(.*)  /$1 break;
      ## nginx需要访问hmall,所有hmall的镜像也只能叫hmall,否则这里就要改
            proxy_pass http://hmall:8080;
        }
    }
    server {
        listen       18081;
        # 指定前端项目所在的位置
        location / {
            root /usr/share/nginx/html/hmall-admin;
        }

        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }
        location /api {
            rewrite /api/(.*)  /$1 break;
            proxy_pass http://hmall:8080;
        }
    }
}
  1. 把今天 nginx 的静态页面和配置文件上传的服务器

  2. 要实现数据卷的挂载

    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 test \
      nginx
    
  3. 开放服务器的 18080 和 18081 端口

  4. 访问:18080 和 18081 端口

遇到的问题

在项目打包的过程中报如下错误:

[!WARNING]

Fatal error compiling: 无效的目标发行版: 11

这是因为我下载的 jdk 是 8,但是项目采用的编码形式是 11,而且也用到了 java11 的新特性

<!--子工程的配置-->
<properties>
    <maven.compiler.source>11</maven.compiler.source>
    <maven.compiler.target>11</maven.compiler.target>
</properties>
<!--父工程的配置-->
<build>
    <pluginManagement>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.8.1</version>
                <configuration>
                    <source>11</source> <!-- depending on your project -->
                    <target>11</target> <!-- depending on your project -->
                </configuration>
            </plugin>
        </plugins>
    </pluginManagement>
</build>

最后重新下载 Java11,解决问题。

DockerCompose

docker-compose.yml 文件

Docker Compose 通过一个单独的 docker-compose.yml 模板文件(YAML 格式)来定义一组相关联的应用容器,帮助我们实现多个相互关联的 Docker 容器的快速部署。

大白话就是:之前需要一个一个部署容器,有了 DockerCompose 文件之后,只需要让 docker 执行 DockerCompose 的配置,实现一个指令部署多个容器

DockerCompose 的语法和docker run 命令是对应关系:

# 一个docker-compose.yml文件就是一个项目(project)
version: '3.8' # 从 Docker Compose v2 开始,version 字段已不再必要

services: # 是 Docker Compose 文件的核心部分,用于定义需要运行的服务(容器)
  mysql: # 是服务(容器)的名称,可以根据需要自定义
    image: mysql # 镜像名
    container_name: mysql # 容器名 --name mysql
    ports: # 端口映射:-p 3306:3306
      - '3306:3306'
    environment: # 配置环境变量:-e TZ=Asia/Shanghai
      TZ: Asia/Shanghai
      MYSQL_ROOT_PASSWORD: 123
    volumes: # 配置数据卷:-v ./mysql/data:/var/lib/mysql
      - './mysql/conf:/etc/mysql/conf.d'
      - './mysql/data:/var/lib/mysql'
    networks: # 配置网络 --network hmall
      - new
networks:
  new:
    name: hmall

一个完整的 DockerCompose 文件:

version: '3.8' # 从 Docker Compose v2 开始,version 字段已不再必要

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: #Java应用容器
    build: # 这就就是替换:docker build -t hmall . 这个命令
      context: . # 这个 . 表示当前目录,是一种相对路径的写法
      dockerfile: Dockerfile # dockerfile的文件名
    container_name: hmall
    ports:
      - '8080:8080'
    networks:
      - hm-net
    depends_on: # 告诉docker当前应用依赖mysql容器,这样就会先创建mysql容器
      - 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 # 网络的名字

version

version: '3.8' 是 Docker Compose 文件的版本号,不同版本的 Docker Compose 文件格式支持的功能略有不同。因此, Docker Compose 文件的版本号不能随意修改,因为它决定了 Docker Compose 文件的语法和功能支持范围。

常见的 Docker Compose 文件版本

版本号 说明
version: '1' 最早的 Docker Compose 文件格式,功能较为简单,已逐渐被淘汰。
version: '2' 支持多容器服务(services),引入了网络和卷的高级配置。
version: '3' version: '2' 的基础上进行了优化,支持 Docker Swarm 模式。
version: '3.8' version: '3' 的子版本,支持更多新特性(如 name 字段)。

如何选择版本

  • 根据 Docker Compose 版本
    • 如果你的 Docker Compose 版本是 1.x,则支持的 Compose 文件版本为 1.x2.x3.x
    • 如果你的 Docker Compose 版本是 2.x,则支持的 Compose 文件版本为 3.x 及以上。
  • 根据功能需求
    • 如果需要使用 Docker Swarm 模式,建议使用 version: '3.x'
    • 如果只是简单的单机部署,version: '2.x' 也足够。
  • 根据 Docker 引擎版本
    • Docker Compose 文件版本需要与 Docker 引擎版本兼容。例如:
      • Docker Engine 20.10+ 支持 Compose 文件版本 3.8
      • Docker Engine 17.12+ 支持 Compose 文件版本 3.0

version不再需要

在旧版本的 Docker Compose 中,version 字段用来指定 docker-compose.yml 文件的版本,该版本会影响文件里可使用的语法和功能。不过从 Docker Compose v2 开始,version 字段已不再必要,继续使用它就会触发此警告:WARN[0000] /root/nginxproxymanager/docker-compose.yml: 'version' is obsolete

halo的DockerCompose

# version: "3" # 从 Docker Compose v2 开始,version 字段已不再必要

    services:
      halo:
        image: registry.fit2cloud.com/halo/halo:2.20
        restart: on-failure:3
        depends_on:
          halodb:
            condition: service_healthy
        networks:
          halo_network:
        volumes:
          - ./halo2:/root/.halo2
        ports:
          - "8090:8090"
        healthcheck:
          # http://localhost:8090 无需替换为服务器的 IP 地址。 
          # 因为在 Docker 容器的环境中,localhost 指的是容器自身。
          # 也就是说,http://localhost:8090 代表的是在当前 halo 容器内部,监听 8090 端口的服务。
          # 由于健康检查是在容器内部执行的,所以使用 localhost 就能够正确地访问到容器内运行的 halo 服务。
          test: ["CMD", "curl", "-f", "http://localhost:8090/actuator/health/readiness"]
          interval: 30s
          timeout: 5s
          retries: 5
          start_period: 30s
        environment:
          # JVM 参数,默认为 -Xmx256m -Xms256m,可以根据实际情况做调整,置空表示不添加 JVM 参数
          - JVM_OPTS=-Xmx256m -Xms256m
        command:
          - --spring.r2dbc.url=r2dbc:pool:mysql://halodb:3306/halo
          - --spring.r2dbc.username=root
          # MySQL 的密码,请保证与下方 MYSQL_ROOT_PASSWORD 的变量值一致。
          - --spring.r2dbc.password=o#DwN&JSa56
          - --spring.sql.init.platform=mysql
          # 外部访问地址,请根据实际需要修改
          - --halo.external-url=http://localhost:8090/

      halodb:
        image: mysql:8.1.0
        restart: on-failure:3
        networks:
          halo_network:
        command: 
          - --default-authentication-plugin=caching_sha2_password
          - --character-set-server=utf8mb4
          - --collation-server=utf8mb4_general_ci
          - --explicit_defaults_for_timestamp=true
        volumes:
          - ./mysql:/var/lib/mysql
          - ./mysqlBackup:/data/mysqlBackup
        healthcheck:
          test: ["CMD", "mysqladmin", "ping", "-h", "127.0.0.1", "--silent"]
          interval: 3s
          retries: 5
          start_period: 30s
        environment:
          # 请修改此密码,并对应修改上方 Halo 服务的 SPRING_R2DBC_PASSWORD 变量值
          - MYSQL_ROOT_PASSWORD=o#DwN&JSa56
          - MYSQL_DATABASE=halo

    networks:
      halo_network:

restart:配置容器的重启策略

  • on-failure:3 表示当容器因错误退出时,最多尝试重启 3 次。
  • no:容器退出后不会自动重启,这是默认的重启策略
  • always:无论容器因何种原因退出(正常退出或异常退出),Docker 都会自动重启该容器,即使在 Docker 守护进程重启后,该容器也会被自动启动。
  • unless-stopped:除非用户手动停止容器,否则容器在退出后会自动重启,即使 Docker 守护进程重启,该容器也会自动启动。与 always 不同的是,如果用户手动停止了容器,在 Docker 守护进程重启时,该容器不会自动启动

depends_on:指定服务之间的依赖关系,halo 服务依赖于 halodb 服务,并且只有当 halodb 服务处于健康状态时,halo 服务才会启动。也就是会先创建 halodb 服务

environment:设置容器的环境变量

  • JVM_OPTS=-Xmx256m -Xms256m 用于配置 Java 虚拟机的堆内存大小
  • MYSQL_ROOT_PASSWORD 用于设置 root 用户的密码
  • MYSQL_DATABASE 用于创建名为 halo 的数据库

command:覆盖容器启动时默认执行的命令,这里配置了 halo 服务连接 MySQL 数据库的相关参数,包括数据库连接 URL、用户名、密码等。用于配置 MySQL 服务器的参数,包括默认认证插件、字符集、排序规则等

运行参数详解:

参数名 描述
spring.r2dbc.url 数据库连接地址,详细可查阅下方的 数据库配置
spring.r2dbc.username 数据库用户名
spring.r2dbc.password 数据库密码
spring.sql.init.platform 数据库平台名称,支持 postgresqlmysqlmariadbh2
halo.external-url 外部访问链接,如果需要在公网访问,需要配置为实际访问地址

数据库配置:

链接方式 链接地址格式 spring.sql.init.platform
PostgreSQL r2dbc:pool:postgresql://{HOST}:{PORT}/{DATABASE} postgresql
MySQL r2dbc:pool:mysql://{HOST}:{PORT}/{DATABASE} mysql
MariaDB r2dbc:pool:mariadb://{HOST}:{PORT}/{DATABASE} mariadb
H2 Database r2dbc:h2:file:///${halo.work-dir}/db/halo-next?MODE=MySQL&DB_CLOSE_ON_EXIT=FALSE h2

基础命令

docker compose [OPTIONS] [COMMAND]

其中,OPTIONS 和 COMMAND 都是可选参数,比较常见的有:

  • OPTIONS

    参数或指令 说明
    -f 指定 compose 文件的路径和名称
    -p 指定 project 名称。project 就是当前 compose 文件中设置的多个 service 的集合,是逻辑概念
  • COMMAND

    参数或指令 说明
    up 创建并启动所有 service 容器
    down 停止并移除所有容器、网络
    ps 列出所有启动的容器
    logs 查看指定容器的日志
    stop 停止容器
    start 启动容器
    restart 重启容器
    top 查看运行的进程
    exec 在指定的运行中容器中执行命令

操作

# 删除所有容器
root@hcss-ecs-1b9f:~# docker rm -f $(docker ps -qa)
2db31fdcc4c0
4750e111899a
cf3d698e83e6

# 删除 hmall镜像
root@hcss-ecs-1b9f:~# docker rmi hmall
Untagged: hmall:latest
Deleted: sha256:82fd88f5fd5bfa054acd6b5072e1356787a91fa618d3528d25514c78398bf965

# 使用compose创建镜像
root@hcss-ecs-1b9f:~# docker compose up -d
[+] Building 16.6s (8/8) FINISHED                                                                           docker:default
 => [hmall internal] load build definition from Dockerfile                                                            0.1s
 => => transferring dockerfile: 298B                                                                                  0.0s
 => [hmall internal] load metadata for docker.io/library/openjdk:11.0-jre-buster                                     15.8s
 => [hmall internal] load .dockerignore                                                                               0.0s
 => => transferring context: 2B                                                                                       0.0s
 => [hmall 1/3] FROM docker.io/library/openjdk:11.0-jre-buster@sha256:3546a17e6fb4ff4fa681c38f3f6644efd393f9bb7ed6eb  0.0s
 => [hmall internal] load build context                                                                               0.6s
 => => transferring context: 68.24MB                                                                                  0.6s
 => CACHED [hmall 2/3] RUN ln -snf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && echo Asia/Shanghai > /etc/tim  0.0s
 => CACHED [hmall 3/3] COPY hm-service.jar /app.jar                                                                   0.0s
 => [hmall] exporting to image                                                                                        0.0s
 => => exporting layers                                                                                               0.0s
 => => writing image sha256:bc11adb3bb71e004b19821c704c94ae6443f78ac17e85049fc4380b4ce0554d5                          0.0s
 => => naming to docker.io/library/root-hmall                                                                         0.0s
[+] Running 3/4
 ⠇ Network hmall    Created                                                                                           1.9s
 ✔ Container mysql  Started                                                                                           1.1s
 ✔ Container hmall  Started                                                                                           1.1s
 ✔ Container nginx  Started                                                                                           1.4s
root@hcss-ecs-1b9f:~# docker ps
CONTAINER ID   IMAGE        COMMAND                  CREATED         STATUS         PORTS                                                                           NAMES
db377e5383a8   nginx        "/docker-entrypoint.…"   9 minutes ago   Up 9 minutes   80/tcp, 0.0.0.0:18080-18081->18080-18081/tcp, :::18080-18081->18080-18081/tcp   nginx
707be506fa7d   root-hmall   "java -jar /app.jar"     9 minutes ago   Up 9 minutes   0.0.0.0:8080->8080/tcp, :::8080->8080/tcp                                       hmall
85fec0fe3825   mysql        "docker-entrypoint.s…"   9 minutes ago   Up 9 minutes   0.0.0.0:3306->3306/tcp, :::3306->3306/tcp, 33060/tcp                            mysql
root@hcss-ecs-1b9f:~# docker network ls
NETWORK ID     NAME      DRIVER    SCOPE
944bbb7fa383   bridge    bridge    local
4cfd144f7a9a   hmall     bridge    local
614dfc283894   host      host      local
7850dabd07e4   none      null      local
6bb868db1b7a   test      bridge    local

服务(容器)名字

当使用 docker compose up -d 命令启动容器时,容器的名称由项目名称、服务名称和一个递增的实例编号组成,下面为你详细介绍其确定方式并举例说明。

确定方式

1. 项目名称

  • 默认规则:默认情况下,项目名称是 docker-compose.yml 文件所在目录的基本名称。例如,若 docker-compose.yml 文件存放在 /home/user/my_project 目录下,那么项目名称就是 my_project
  • 手动指定:你可以通过设置 COMPOSE_PROJECT_NAME 环境变量或者使用 -p 选项来手动指定项目名称。

2. 服务名称

服务名称在 docker-compose.yml 文件中的 services 部分进行定义,每个服务对应一个键,这个键就是服务名称。

3. 实例编号

实例编号是一个递增的数字,从 1 开始。如果一个服务只启动一个实例,那么实例编号就是 1;如果启动多个实例,编号会依次递增。

示例

示例 1:使用默认项目名称

假设 docker-compose.yml 文件内容如下:

version: '3'
services:
  web_app:
    image: nginx:latest
    restart: unless-stopped

并且该文件存放在 /home/user/web_project 目录下。当你在该目录下执行 docker compose up -d 命令时:

  • 项目名称:根据默认规则,项目名称为 web_project
  • 服务名称:在 docker-compose.yml 文件中定义的服务名称是 web_app
  • 实例编号:由于只启动一个实例,实例编号为 1。

最终创建的容器名称为 web_project_web_app_1

示例 2:手动指定项目名称

同样使用上述 docker-compose.yml 文件,在执行 docker compose up -d 命令时,使用 -p 选项手动指定项目名称:

docker compose -p custom_project up -d

此时:

  • 项目名称:通过 -p 选项指定为 custom_project
  • 服务名称:依然是 web_app
  • 实例编号:由于只启动一个实例,实例编号为 1。

最终创建的容器名称为 custom_project_web_app_1

示例 3:启动多个实例

修改 docker-compose.yml 文件,使用 deploy 部分指定服务的副本数量:

version: '3'
services:
  web_app:
    image: nginx:latest
    restart: unless-stopped
    deploy:
      replicas: 2

假设该文件存放在 /home/user/web_project 目录下,执行 docker compose up -d 命令后:

  • 项目名称:默认项目名称为 web_project
  • 服务名称:web_app
  • 实例编号:由于指定了 2 个副本,会创建两个容器,实例编号分别为 1 和 2。

最终创建的两个容器名称分别为 web_project_web_app_1web_project_web_app_2


转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 1909773034@qq.com

×

喜欢就点赞,疼爱就打赏