docker使用小记

194 阅读14分钟

厚积薄发,静水流深,今天介绍docker的一些使用

安装Docker

安装

以Ubuntu 22.04 为例,安装 Docker(其他Linux版本,例如 CentOS,也可以在官网找到安装步骤)。

CentOS 安装和卸载说明:docs.docker.com/engine/inst…

卸载旧版本(如果有)

 for pkg in docker.io docker-doc docker-compose docker-compose-v2 podman-docker containerd runc; do sudo apt-get remove $pkg; done

更新包索引并安装依赖

 sudo apt-get update
 ​
 sudo apt-get install ca-certificates curl gnupg

添加Docker官方GPG密钥

 sudo mkdir -m 0755 -p /etc/apt/keyrings
 ​
 curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
 ​
 sudo chmod a+r /etc/apt/keyrings/docker.gpg

添加Docker APT仓库

 echo \
   "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \
   $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
   sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

安装Docker引擎

 sudo apt-get update
 ​
 sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

启动Docker服务

 sudo systemctl start docker

查看Docker版本

 docker version

防止Docker自动更新(非必要)

 sudo apt-mark hold docker-ce

允许非root用户使用Docker(非必要)

默认情况下只有root权限才可以使用Docker,使用下列命令将用户加入到Docker组,以便该用户无需 sudo 即可执行 docker 命令:

 sudo usermod -aG docker $USER
 ​
 newgrp docker

注意: 将本地用户添加到 docker 组后,请确保注销并再次登录。

运行Hello World

 sudo docker run hello-world

阿里云镜像加速

Docker 官方提供了镜像仓库是 DockerHub ,但是服务器是在国外的,在国内使用下载镜像会很慢,所以我们配置阿里云镜像服务后,下载镜像会快很多。

注册并登录阿里云

网址:https://www.aliyun.com/

获取镜像加速地址

控制台搜索镜像:

image-20240916234436614

配置镜像加速

按照上面配置镜像加速的脚本,依次执行:

 sudo mkdir -p /etc/docker
 sudo tee /etc/docker/daemon.json <<-'EOF'
 {
   "registry-mirrors": ["https://xxxxxxx.mirror.aliyuncs.com"]    # 这里配置的是你自己的地址,别搞错了
 }
 EOF
 # 重新加载服务
 sudo systemctl daemon-reload
 # 重启docker服务
 sudo systemctl restart docker

有了加速器,下载镜像速度能快很多。

镜像操作

搜索镜像

 # 搜索镜像
 docker search nginx
 ​
 # 搜索镜像,同时显示显示的结果,只显示10条,不加参数,默认显示25条
 docker search --limit 10 nginx

说明:

 搜索会列出很多的镜像,分别是不同的账户、组织提交的,包括名称、描述等信息, STARTS 是受欢迎程度,用星星数量表示,OFFICIAL 栏为OK的表示是官方的镜像,AUTOMATED 表示镜像是否由自动化流程构建。

下载镜像

 # 拉取最新版本的镜像
 docker pull nginx
 ​
 # 拉取指定版本的镜像:
 docker pull nginx:1.27.1

说明:

 每个镜像都有 tag,也就是版本,如果不指定tag,默认拉取的就是最新版本。
 可以登录 dockerhub,查看镜像有哪些版本。

查看镜像

 # 查看本地所有镜像
 docker images
 ​
 # 查看本地所有镜像,包括中间层(intermediate layers)。
 docker images -a

说明:

 显示本地的镜像信息中,包含了镜像的名称、版本标签、镜像ID,什么时候创建的,镜像的大小。

删除镜像

 # 删除镜像, 通过id删除(可以只输入id的前几位)
 docker rmi 镜像ID
 ​
 # 强制删除
 docker rmi -f 镜像ID
 ​
 # 只会删除最新版本的镜像
 docker rmi 镜像名称
 # 删除指定版本的镜像
 docker rmi 镜像名称:版本tag
 # 删除多个
 docker rmi 镜像ID1 镜像ID2
 # 删除所有镜像,慎用或不用,docker images -qa是获取到镜像的ID
 docker rmi -f $(docker images -qa)

查看镜像/容器/数据卷的占用空间

docker system df
说明:
Images:所有镜像占用的空间,包括拉取的镜像、本地构建的镜像。
Containers:容器的数量、和占用的空间。
Local Volumes:本地数据卷的空间。
Build Cache:镜像构建过程中,产生的缓存数据。

导出镜像

# 使用 docker save 命令将本地的 Docker 镜像保存为一个 tar 文件, -o 指定导出的镜像文件保存路径
docker save -o /path/to/镜像名.tar 镜像名:版本号

导入镜像

 # 可以使用 docker load 命令将镜像文件的 tar 包导入, -i 指定加载的镜像文件路径
 docker load -i /path/to/your_image.tar

将容器提交成镜像

 # 根据容器变更创建镜像, 得到该容器此时状态的新镜像
 docker commit -a wwjdr -m "wwjdr's nginx image" nginx wwjdrnginx:v6.0

说明:

 root@wwjdr-ubuntu:/software/nginx# docker commit --help
 ​
 Usage:  docker commit [OPTIONS] CONTAINER [REPOSITORY[:TAG]]    #命令描述
 ​
 Create a new image from a container's changes   # 将容器的变更创建为一个新镜像
 ​
 Aliases:
   docker container commit, docker commit
 ​
 Options:
   -a, --author string    Author (e.g., "John Hannibal Smith <hannibal@a-team.com>")     # 作者
   -c, --change list      Apply Dockerfile instruction to the created image
   -m, --message string   Commit message     # 描述信息
   -p, --pause            Pause container during commit (default true) # 是否在commit过程中暂停容器的运行, 默认true

镜像分享至docker

通过docker login 登录dockerhub, 通过docker push推送至个人仓库, 具体略...

容器操作

启动容器

 # 启动容器
 docker run -d --name nginx --restart=always -p 80:80 -v /software/nginx/html:/usr/share/nginx/html nginx:1.27.1
 说明:
 docker run nginx: 是最基本的启动命令
 ​
 -d: 表示启动并后台运行nginx
 ​
 --name nginx: 容器名字
 ​
 --restart=always 自动重启
 ​
 -p 80:80: 映射端口, 服务器的80端口映射容器内的80端口
 ​
 -v /software/nginx/html:/usr/share/nginx/html: 目录挂载, 外部的/software/nginx/html目录与容器内部的/usr/share/nginx/html目录映射
 ​
 nginx:1.27.1: 启动的镜像及版本号

查看容器

 # 查看运行中的容器
 docker ps
 ​
 # 查看所有容器,包括停止的
 docker ps -a
 ​
 # 查看最近创建的容器
 docker ps -l
 ​
 # 查看容器,只显示容器编号
 docker ps -q
 ​
 # 查看最近n个创建的容器
 docker ps -n 5  # 查看最近创建的5个容器

启动/重启容器

 # 启动已经停止的容器
 docker start 容器ID/名称
 ​
 # 重启容器
 docker restart 容器ID/名称

删除容器

 # 删除已停止的容器
 docker rm 容器ID/名称
 ​
 # 强制删除容器,运行中的也可以删除
 docker rm -f 容器ID/名称
 ​
 # 删除全部容器
 docker rm -f $(docker ps -aq)
 # 或者
 docker ps -a -q | xargs docker rm

停止容器

# 停止容器(id输入前几位即可)
docker stop 容器ID/名称

# 强制停止容器
docker kill 容器ID/名称
docker stop 和 docker kill 的区别:
	docker stop比较温柔,它会给容器发送一个TERM信号,给容器充足时间(默认10秒)保存数据,让容器自动安全停止运行,超时后再给系统发送SIGKILL的系统信号强行kill掉进程,最后转变为stop状态。而docker kill则比较生猛,它会直接给系统发送SIGKILL的系统信号强行kill掉进程。

重启策略

docker run -d --name myredis -p 6379:6379 --restart=always redis
 其中的 --restart 参数指定了重启的策略, --restart 可以设置为如下值:
     no:默认策略,在容器退出时不进行重启。
     always:无论容器退出状态如何,都会尝试重启容器。
     on-failure:只有在容器以非零状态码退出时才尝试重启容器。
     unless-stopped:在容器退出或守护进程重启时,始终重启容器,除非用户明确停止了容器。
     
 如果容器已经启动了,可以使用 update 命令修改容器的重启策略:
 docker update --restart=always <container_id>

查看容器日志

 # 查看容器日志
 docker logs 容器ID/名称

查看容器/镜像的信息

 # 查看容器详细信息
 docker inspect 容器ID/名称
 ​
 说明:
     docker inspect 是一个用于获取容器或镜像(也可以查看镜像)详细信息的命令。通过这个命令,可以查看容器的配置、网络设置、存储卷挂载等信息。使用该命令,可以更好地了解容器或镜像的运行状态和配置情况。

拷贝文件

 # 将宿主机的文件拷贝到容器
 docker cp 宿主机路径 容器ID(容器名):容器内路径
 ​
 # 将容器的文件拷贝到宿主机
 docker cp 容器ID(容器名):容器内路径 宿主机路径

导出

 # 导出
 docker export 容器ID/名称 > 文件.tar

导入

 # 从tar包导入为
 docker import 文件.tar 镜像名称:版本标签

目录挂载

 # 启动容器
 docker run -d --name nginx -p 80:80 -v /software/nginx/html:/usr/share/nginx/html nginx:1.27.1
 ​
 -v /software/nginx/html:/usr/share/nginx/html: 
     目录挂载, 外部的/software/nginx/html目录与容器内部的/usr/share/nginx/html目录映射, 内部的该目录会与外部的目录保持一模一样
     外部目录新增文件或者修改文件, 容器内部的目录也会同步新增修改
     容器内部新增文件或者修改文件, 外部目录的目录也会同步新增修改
     当前案例是挂载目录, 只挂载一个文件也是可以的
     目录挂载的情况下, docker启动容器会以外部目录为
     删除容器, 服务器上目录挂载的目录不会被删除

卷映射

 docker run -d --name nginx -p 80:80 -v /software/nginx/html:/usr/share/nginx/html -v nginx_conf:/etc/nginx nginx
 ​
 -v nginx_conf:/etc/nginx: 
     卷映射, 启动容器时会先以内部目录为准, 再在外部创建具有相同文件内容的目录, 如果volume是空的而容器中的目录有内容,那么docker会将容器目录中的内容拷贝到volume中,但是如果volume中已经有内容,则会将容器中的目录覆盖。
     默认情况下, 卷目录挂载的目录会存放在 /var/lib/docker/volumes/<卷映射名>/_data 中
     删除容器, 服务器上卷映射的目录不会被删除

image-20240916032640787

 # 查看docker中存在的卷
 docker volume ls
 ​
 # 查看卷在服务器上的位置
 docker inspect [VOLUME_NAME]
 ​
 # 删除不用的卷:如果卷不再使用,可以删除它们以释放空间
 docker volume rm [VOLUME_NAME]
 ​
 # 清理未使用的卷:使用以下命令来清理那些不再由任何容器使用的卷
 docker volume prune

同步容器时间

 启动容器时, 指定时间同步:
 docker run ... -v /etc/localtime:/etc/localtime:ro -v /etc/timezone:/etc/timezone:ro ...
 ​
 或者:
 ​
 docker run -d \
   --name my_container \
   -e TZ=Asia/Shanghai \
   your_image

如果容器内的时间已经不对了按照以下操作:

 1, 首先进入到容器内
 ​
 2, 然后查看一下时间: date
 ​
 ​
 3, 如果时间不正确,则需要调整时区, 运行如下命令,来选择时区:tzselect
 ​
 4, 会显示选择时区的选项,依次选择亚洲、中国、北京,最后确定
 ​
 5, 然后再运行如下命令:cp /usr/share/zoneinfo/Asia/Shanghai  /etc/localtime
 ​
 6, 此时再运行一下 date 命令查看一下时间是否正确
 ​
 7, 重启容器(该步必要性待验证)
 ​
 ​
 如果容器内部的时间是正确的,而 tomcat 打印的日志时间不正确,则需要修改 tomcat 的配置。
 首先进入容器,然后进入文件夹 /usr/local/tomcat/bin 部,编辑文件 catalina.sh,在配置文件前面添加如下配置:
 CATALINA_OPTS="$CATALINA_OPTS -Duser.timezone=Asia/Shanghai"

容器间的通信

docker启动了3个nginx:

image-20240916035212019

现在, 需要访问其他容器

通过宿主机端口

1, 先进入容器; 2, 通过外部端口访问

image-20240916035404894

这样也行, 但是相当于兜了个圈, nginx2访问别的容器, 先出去到宿主机, 再通过宿主机端口(80/81/82)找到具体的容器, 再访问具体容器

通过docker网络

其实, docker启动后, 会生成自己的网卡:

image-20240916035738931

docker在启动容器时, 会为每个容器分配一个ip, 并加入到docker网络里:

使用 docker container inspect nginx 可以查看容器的细节, 其中就有该容器注册到docker网络的ip:

image-20240916040155416

通过容器在docker中的ip容器内部端口直接访问:

image-20240916040458993

自定义网络

通过docker网络ip访问其他容器可行, 但是ip是会变的, 因此, 可以使用docker自定义网络, 更方便的访问其他容器

通过docker netword create [自定义网络名]创建:

image-20240916041315499

容器名就是域名:

image-20240916041927162

常用中间件部署

docker部署nginx

 docker run -d \                                     # 后台运行
 --name nginx \                                      # 容器起名
 --restart always                                    # 开机自启
 -p 80:80 \                                          # 端口映射
 -v /software/nginx/html:/usr/share/nginx/html \     # 目录挂载
 -v /software/nginx/conf:/etc/nginx \                # 目录挂载
 -v /wwjfiles/static/:/wwjfiles \                    # 目录挂载(静态文件挂载)
 -v /etc/localtime:/etc/localtime:ro \               # 同步时间
 -v /etc/timezone:/etc/timezone:ro \                 # 同步时区
 nginx                                               # 镜像

docker部署mysql

 docker run -d \
 --name mysql \
 --restart always \
 -p 3306:3306 \
 -v /software/mysql/conf:/etc/mysql/conf.d \     # mysql配置文件
 -v /software/mysql/data:/var/lib/mysql \        # mysql数据
 -v /etc/localtime:/etc/localtime:ro \               # 同步时间
 -v /etc/timezone:/etc/timezone:ro \                 # 同步时区
 -e MYSQL_ROOT_PASSWORD=root \                   # root账号密码
 mysql:8.4.2

docker部署redis

 docker run -d \
 --name redis \
 --restart always \
 -p 6379:6379 \
 -v /software/redis/data:/bitnami/redis/data \
 -v /etc/localtime:/etc/localtime:ro \               # 同步时间
 -v /etc/timezone:/etc/timezone:ro \                 # 同步时区
 -e REDIS_PASSWORD=123456 \
 bitnami/redis

docker部署Tomcat

搜索镜像

首先搜索镜像,找到官方镜像:

 docker search tomcat

拉取镜像

找到官方镜像,执行拉取,命令:

 docker pull tomcat

启动容器

镜像下载完成就,就可以启动容器了。使用后台模式启动容器,并映射 8080 端口,并进行相应的容器卷挂载。命令:

 docker run -d -p 8080:8080 --name tomcat \
 -v /software/tomcat/webapps:/usr/local/tomcat/webapps \
 -v /software/tomcat/logs:/usr/local/tomcat/logs tomcat

存在的坑

容器启动后,访问宿主机的 8080 端口,可能会报 404 错误。

因为tomcat 访问到的8080带三脚猫的首页,是在 webapps 目录下的,但是新版的 tomcat 的 webapps 下面是空,静态资源被放置到 webapps.dist 目录下了,所以就找不到首页了。

处理: 我们可以进入到容器,将webapps.dist 目录下的内容拷贝到 webapps 目录下面。

 # 进入容器
 docker exit -it tomcat容器ID /bin/bash
 ​
 # 进入到webapps.dist/目录
 cd webapps.dist/
 ​
 # 将webapps.dist/目录下的内容拷贝到webapps/目录下
 cp -r * ../webapps/

拷贝完成后,重新刷新页面,出现了三脚猫。

同步容器内时间

参考容器操作-同步容器时间

如果容器内部的时间是正确的,而 tomcat 打印的日志时间不正确,则需要修改 tomcat 的配置。

首先进入容器,然后进入文件夹 /usr/local/tomcat/bin 部,编辑文件 catalina.sh,在配置文件前面添加如下配置:

 CATALINA_OPTS="$CATALINA_OPTS -Duser.timezone=Asia/Shanghai"

Docker Compose命令式安装

docker compost可以批量启动多个镜像服务

配置启动一个应用

博客应用, 涉及mysql服务和博客wordpress服务

新增yml文件, 配置及说明:

 name: myblog  # 应用名
 services:  # 配置启动的服务
   mysql:  # 服务1: mysql
     container_name: mysql  # 容器名
     image: mysql:8.0  # 镜像及版本
     ports:  # 端口配置
       - "3306:3306"  # 数据写法, 将主机的3306端口映射到容器的3306端口
     environment:  # 环境变量配置
       - MYSQL_ROOT_PASSWORD=123456  # 设置mysql root账户的密码
       - MYSQL_DATABASE=wordpress  # 在容器启动时创建一个名为wordpress的数据库
     volumes:  # 挂载配置
       - mysql-data:/var/lib/mysql  # 卷映射,将主机的mysql-data卷映射到容器的/var/lib/mysql目录(卷映射需要将卷名在顶级节点volumes中声明)
       - /app/myconf:/etc/mysql/conf.d  # 目录挂载,将主机的/app/myconf目录挂载到容器的/etc/mysql/conf.d目录
     restart: always  # 容器自启动
     networks:  # 加入docker网络的配置
       - blog  # 加入自定义网络blog
 
   wordpress:  # 服务2: wordpress
     image: wordpress  # 使用wordpress镜像
     ports:  # 端口配置
       - "8080:80"  # 将主机的8080端口映射到容器的80端口
     environment:  # 环境变量配置
       WORDPRESS_DB_HOST: mysql  # 环境变量, 依赖的 数据库主机名
       WORDPRESS_DB_USER: root  # 环境变量, 依赖的 数据库用户名
       WORDPRESS_DB_PASSWORD: 123456  # 环境变量, 依赖的 数据库用户的密码
       WORDPRESS_DB_NAME: wordpress  # 环境变量, 依赖的 数据库名
     volumes:  # 挂载配置
       - wordpress:/var/www/html  # 卷映射,将主机的wordpress卷映射到容器的/var/www/html目录(卷映射需要将卷名在顶级节点volumes中声明)
     restart: always  # 容器自启动
     networks:  # 加入docker网络的配置
       - blog  # 加入自定义网络blog
     depends_on:  # 定义启动依赖
       - mysql  # 在wordpress服务启动之前,确保mysql服务已经启动
 
 volumes:  # 定义卷, 上述配置用到的卷映射都需要在此声明
   mysql-data:  # mysql数据卷
   wordpress:  # wordpress数据卷
 
 networks:  # 定义网络
   blog:  # 自定义网络blog

docker启动应用:

 # 上线应用, 默认以compose.yml启动
 docker compose up -d
 ​
 # -f 指定yml配置文件启动
 docker compose -f compose.yml up -d

启动结果如下:

image-20240916174314881

增量更新

修改配置后, docker会根据容器配置是否调整, 增量更新

下线应用

下线应用, 可以下线时指定是否删除镜像, 是否删除卷映射等, 具体看docker compose down --help

附录

halo博客网址部署

 services:
   halo:
     container_name: halo
     image: registry.fit2cloud.com/halo/halo:2.19
     restart: on-failure:3
     volumes:
       - /software/halo:/root/.halo2
     ports:
       - "8090:8090"
     healthcheck:
       test: ["CMD", "curl", "-f", "http://192.168.0.113:8090/actuator/health/readiness"]
       interval: 30s
       timeout: 5s
       retries: 5
       start_period: 30s
     command:
       # mysql数据库配置, 其他数据库配置参考halo官网
       - --spring.r2dbc.url=r2dbc:pool:mysql://192.168.0.113:3306/halo
       - --spring.r2dbc.username=root
       - --spring.r2dbc.password=root
       - --spring.sql.init.platform=mysql
       # 外部访问地址,请根据实际需要修改
       - --halo.external-url=http://192.168.0.113:8090/

或者halo和mysql一起部署:

 services:
   halo:
     image: registry.fit2cloud.com/halo/halo:2.19
     restart: on-failure:3
     depends_on:
       halodb:
         condition: service_healthy
     networks:
       halo_network:
     volumes:
       - ./halo2:/root/.halo2
     ports:
       - "8090:8090"
     healthcheck:
       test: ["CMD", "curl", "-f", "http://localhost:8090/actuator/health/readiness"]
       interval: 30s
       timeout: 5s
       retries: 5
       start_period: 30s
     command:
       - --spring.r2dbc.url=r2dbc:pool:postgresql://halodb/halo
       - --spring.r2dbc.username=halo
       # PostgreSQL 的密码,请保证与下方 POSTGRES_PASSWORD 的变量值一致。
       - --spring.r2dbc.password=openpostgresql
       - --spring.sql.init.platform=postgresql
       # 外部访问地址,请根据实际需要修改
       - --halo.external-url=http://localhost:8090/
   halodb:
     image: postgres:15.4
     restart: on-failure:3
     networks:
       halo_network:
     volumes:
       - ./db:/var/lib/postgresql/data
     healthcheck:
       test: [ "CMD", "pg_isready" ]
       interval: 10s
       timeout: 5s
       retries: 5
     environment:
       - POSTGRES_PASSWORD=openpostgresql
       - POSTGRES_USER=halo
       - POSTGRES_DB=halo
       - PGUSER=halo
 
 networks:
   halo_network::

一键启动多个常用中间件

该compose.yml来自雷神雷丰阳

yml

准备一个 compose.yaml文件,所有容器都做了时间同步,这样容器的时间和linux主机的时间就一致了, 内容如下:

 name: devsoft
 services:
   redis:
     image: bitnami/redis:latest
     restart: always
     container_name: redis
     environment:
       - REDIS_PASSWORD=123456
     ports:
       - '6379:6379'
     volumes:
       - redis-data:/bitnami/redis/data
       - redis-conf:/opt/bitnami/redis/mounted-etc
       - /etc/localtime:/etc/localtime:ro
 
   mysql:
     image: mysql:8.0.31
     restart: always
     container_name: mysql
     environment:
       - MYSQL_ROOT_PASSWORD=root
     ports:
       - '3306:3306'
       - '33060:33060'
     volumes:
       - mysql-conf:/etc/mysql/conf.d
       - mysql-data:/var/lib/mysql
       - /etc/localtime:/etc/localtime:ro
 
   rabbit:
     image: rabbitmq:3-management
     restart: always
     container_name: rabbitmq
     ports:
       - "5672:5672"
       - "15672:15672"
     environment:
       - RABBITMQ_DEFAULT_USER=rabbit
       - RABBITMQ_DEFAULT_PASS=rabbit
       - RABBITMQ_DEFAULT_VHOST=dev
     volumes:
       - rabbit-data:/var/lib/rabbitmq
       - rabbit-app:/etc/rabbitmq
       - /etc/localtime:/etc/localtime:ro
   opensearch-node1:
     image: opensearchproject/opensearch:2.13.0
     container_name: opensearch-node1
     environment:
       - cluster.name=opensearch-cluster # Name the cluster
       - node.name=opensearch-node1 # Name the node that will run in this container
       - discovery.seed_hosts=opensearch-node1,opensearch-node2 # Nodes to look for when discovering the cluster
       - cluster.initial_cluster_manager_nodes=opensearch-node1,opensearch-node2 # Nodes eligibile to serve as cluster manager
       - bootstrap.memory_lock=true # Disable JVM heap memory swapping
       - "OPENSEARCH_JAVA_OPTS=-Xms512m -Xmx512m" # Set min and max JVM heap sizes to at least 50% of system RAM
       - "DISABLE_INSTALL_DEMO_CONFIG=true" # Prevents execution of bundled demo script which installs demo certificates and security configurations to OpenSearch
       - "DISABLE_SECURITY_PLUGIN=true" # Disables Security plugin
     ulimits:
       memlock:
         soft: -1 # Set memlock to unlimited (no soft or hard limit)
         hard: -1
       nofile:
         soft: 65536 # Maximum number of open files for the opensearch user - set to at least 65536
         hard: 65536
     volumes:
       - opensearch-data1:/usr/share/opensearch/data # Creates volume called opensearch-data1 and mounts it to the container
       - /etc/localtime:/etc/localtime:ro
     ports:
       - 9200:9200 # REST API
       - 9600:9600 # Performance Analyzer
 
   opensearch-node2:
     image: opensearchproject/opensearch:2.13.0
     container_name: opensearch-node2
     environment:
       - cluster.name=opensearch-cluster # Name the cluster
       - node.name=opensearch-node2 # Name the node that will run in this container
       - discovery.seed_hosts=opensearch-node1,opensearch-node2 # Nodes to look for when discovering the cluster
       - cluster.initial_cluster_manager_nodes=opensearch-node1,opensearch-node2 # Nodes eligibile to serve as cluster manager
       - bootstrap.memory_lock=true # Disable JVM heap memory swapping
       - "OPENSEARCH_JAVA_OPTS=-Xms512m -Xmx512m" # Set min and max JVM heap sizes to at least 50% of system RAM
       - "DISABLE_INSTALL_DEMO_CONFIG=true" # Prevents execution of bundled demo script which installs demo certificates and security configurations to OpenSearch
       - "DISABLE_SECURITY_PLUGIN=true" # Disables Security plugin
     ulimits:
       memlock:
         soft: -1 # Set memlock to unlimited (no soft or hard limit)
         hard: -1
       nofile:
         soft: 65536 # Maximum number of open files for the opensearch user - set to at least 65536
         hard: 65536
     volumes:
       - /etc/localtime:/etc/localtime:ro
       - opensearch-data2:/usr/share/opensearch/data # Creates volume called opensearch-data2 and mounts it to the container
 
   opensearch-dashboards:
     image: opensearchproject/opensearch-dashboards:2.13.0
     container_name: opensearch-dashboards
     ports:
       - 5601:5601 # Map host port 5601 to container port 5601
     expose:
       - "5601" # Expose port 5601 for web access to OpenSearch Dashboards
     environment:
       - 'OPENSEARCH_HOSTS=["http://opensearch-node1:9200","http://opensearch-node2:9200"]'
       - "DISABLE_SECURITY_DASHBOARDS_PLUGIN=true" # disables security dashboards plugin in OpenSearch Dashboards
     volumes:
       - /etc/localtime:/etc/localtime:ro
   zookeeper:
     image: bitnami/zookeeper:3.9
     container_name: zookeeper
     restart: always
     ports:
       - "2181:2181"
     volumes:
       - "zookeeper_data:/bitnami"
       - /etc/localtime:/etc/localtime:ro
     environment:
       - ALLOW_ANONYMOUS_LOGIN=yes
 
   kafka:
     image: 'bitnami/kafka:3.4'
     container_name: kafka
     restart: always
     hostname: kafka
     ports:
       - '9092:9092'
       - '9094:9094'
     environment:
       - KAFKA_CFG_NODE_ID=0
       - KAFKA_CFG_PROCESS_ROLES=controller,broker
       - KAFKA_CFG_LISTENERS=PLAINTEXT://:9092,CONTROLLER://:9093,EXTERNAL://0.0.0.0:9094
       - KAFKA_CFG_ADVERTISED_LISTENERS=PLAINTEXT://kafka:9092,EXTERNAL://[本机IP]:9094
       - KAFKA_CFG_LISTENER_SECURITY_PROTOCOL_MAP=CONTROLLER:PLAINTEXT,EXTERNAL:PLAINTEXT,PLAINTEXT:PLAINTEXT
       - KAFKA_CFG_CONTROLLER_QUORUM_VOTERS=0@kafka:9093
       - KAFKA_CFG_CONTROLLER_LISTENER_NAMES=CONTROLLER
       - ALLOW_PLAINTEXT_LISTENER=yes
       - "KAFKA_HEAP_OPTS=-Xmx512m -Xms512m"
     volumes:
       - kafka-conf:/bitnami/kafka/config
       - kafka-data:/bitnami/kafka/data
       - /etc/localtime:/etc/localtime:ro
   kafka-ui:
     container_name: kafka-ui
     image: provectuslabs/kafka-ui:latest
     restart: always
     ports:
       - 8080:8080
     environment:
       DYNAMIC_CONFIG_ENABLED: true
       KAFKA_CLUSTERS_0_NAME: kafka-dev
       KAFKA_CLUSTERS_0_BOOTSTRAPSERVERS: kafka:9092
     volumes:
       - kafkaui-app:/etc/kafkaui
       - /etc/localtime:/etc/localtime:ro
 
   nacos:
     image: nacos/nacos-server:v2.3.1
     container_name: nacos
     ports:
       - 8848:8848
       - 9848:9848
     environment:
       - PREFER_HOST_MODE=hostname
       - MODE=standalone
       - JVM_XMX=512m
       - JVM_XMS=512m
       - SPRING_DATASOURCE_PLATFORM=mysql
       - MYSQL_SERVICE_HOST=nacos-mysql
       - MYSQL_SERVICE_DB_NAME=nacos_devtest
       - MYSQL_SERVICE_PORT=3306
       - MYSQL_SERVICE_USER=nacos
       - MYSQL_SERVICE_PASSWORD=nacos
       - MYSQL_SERVICE_DB_PARAM=characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true&useUnicode=true&useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true
       - NACOS_AUTH_IDENTITY_KEY=2222
       - NACOS_AUTH_IDENTITY_VALUE=2xxx
       - NACOS_AUTH_TOKEN=SecretKey012345678901234567890123456789012345678901234567890123456789
       - NACOS_AUTH_ENABLE=true
     volumes:
       - /app/nacos/standalone-logs/:/home/nacos/logs
       - /etc/localtime:/etc/localtime:ro
     depends_on:
       nacos-mysql:
         condition: service_healthy
   nacos-mysql:
     container_name: nacos-mysql
     build:
       context: .
       dockerfile_inline: |
         FROM mysql:8.0.31
         ADD https://raw.githubusercontent.com/alibaba/nacos/2.3.2/distribution/conf/mysql-schema.sql /docker-entrypoint-initdb.d/nacos-mysql.sql
         RUN chown -R mysql:mysql /docker-entrypoint-initdb.d/nacos-mysql.sql
         EXPOSE 3306
         CMD ["mysqld", "--character-set-server=utf8mb4", "--collation-server=utf8mb4_unicode_ci"]
     image: nacos/mysql:8.0.30
     environment:
       - MYSQL_ROOT_PASSWORD=root
       - MYSQL_DATABASE=nacos_devtest
       - MYSQL_USER=nacos
       - MYSQL_PASSWORD=nacos
       - LANG=C.UTF-8
     volumes:
       - nacos-mysqldata:/var/lib/mysql
       - /etc/localtime:/etc/localtime:ro
     ports:
       - "13306:3306"
     healthcheck:
       test: [ "CMD", "mysqladmin" ,"ping", "-h", "localhost" ]
       interval: 5s
       timeout: 10s
       retries: 10
   prometheus:
     image: prom/prometheus:v2.52.0
     container_name: prometheus
     restart: always
     ports:
       - 9090:9090
     volumes:
       - prometheus-data:/prometheus
       - prometheus-conf:/etc/prometheus
       - /etc/localtime:/etc/localtime:ro
 
   grafana:
     image: grafana/grafana:10.4.2
     container_name: grafana
     restart: always
     ports:
       - 3000:3000
     volumes:
       - grafana-data:/var/lib/grafana
       - /etc/localtime:/etc/localtime:ro
 
 volumes:
   redis-data:
   redis-conf:
   mysql-conf:
   mysql-data:
   rabbit-data:
   rabbit-app:
   opensearch-data1:
   opensearch-data2:
   nacos-mysqldata:
   zookeeper_data:
   kafka-conf:
   kafka-data:
   kafkaui-app:
   prometheus-data:
   prometheus-conf:
   grafana-data:

启动

# 在 compose.yaml 文件所在的目录下执行
docker compose up -d
# 等待启动所有容器

tip:如果重启了服务器,可能有些容器会启动失败。再执行一遍 docker compose up -d即可。所有程序都可运行成功,并且不会丢失数据。请放心使用。

访问

组件(容器名)介绍访问地址账号/密码特性
Redis(redis)k-v 库你的ip:6379单密码模式:123456已开启AOF
MySQL(mysql)数据库你的ip:3306root/123456默认utf8mb4字符集
Rabbit(rabbit)消息队列你的ip:15672rabbit/rabbit暴露5672和15672端口
OpenSearch(opensearch-node1/2)检索引擎你的ip:9200内存512mb;两个节点
opensearch-dashboardssearch可视化你的ip:5601
Zookeeper(zookeeper)分布式协调你的ip:2181允许匿名登录
kafka(kafka)消息队列你的ip:9092 外部访问:9094占用内存512mb
kafka-ui(kafka-ui)kafka可视化你的ip:8080
nacos(nacos)注册/配置中心你的ip:8848nacos/nacos持久化数据到MySQL
nacos-mysql(nacos-mysql)nacos配套数据库你的ip:13306root/root
prometheus(prometheus)时序数据库你的ip:9090
grafana(grafana)你的ip:3000admin/admin