一溪风月
一溪风月
Published on 2024-01-19 / 135 Visits
0
0

不同docker容器应用访问同一个docker镜像数据库

不同docker容器应用访问同一个docker镜像数据库

场景描述

以本人自己服务器上的应用举例,我首先部署的是halo+mysql应用,按照官网给出的 docker-compose.yml 文件示意,我是这么写的。

version: "3"

services:
  halo:
    image: halohub/halo:2.11
    container_name: halo
    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: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
    container_name: halodb
    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
    ports:
      - "3306:3306"
    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:

当时的机器纯净的就像一张白纸,写完按照命令启动,执行:

docker-compose up -d

OK,没有一点问题。

后来过了几个月,我又想部署一个私人的代码管理器,选来选去选到了 gitea这个项目。开源、免费、轻量,very nice,完美符合我的要求。

部署的时候就有一点点问题了,官网给的 docker-compose.yml文件是这样的。

version: "3"

networks:
  gitea:
    external: false

services:
  server:
    image: gitea/gitea:1.21.4
    container_name: gitea
    environment:
      - USER_UID=1000
      - USER_GID=1000
+      - GITEA__database__DB_TYPE=mysql
+      - GITEA__database__HOST=db:3306
+      - GITEA__database__NAME=gitea
+      - GITEA__database__USER=gitea
+      - GITEA__database__PASSWD=gitea
    restart: always
    networks:
      - gitea
    volumes:
      - ./gitea:/data
      - /etc/timezone:/etc/timezone:ro
      - /etc/localtime:/etc/localtime:ro
    ports:
      - "3000:3000"
      - "222:22"
+    depends_on:
+      - db
+
+  db:
+    image: mysql:8
+    restart: always
+    environment:
+      - MYSQL_ROOT_PASSWORD=gitea
+      - MYSQL_USER=gitea
+      - MYSQL_PASSWORD=gitea
+      - MYSQL_DATABASE=gitea
+    networks:
+      - gitea
+    volumes:
+      - ./mysql:/var/lib/mysql

问题来了,我已经部署了一个mysql镜像了,完全没必要再装另外一个呀,那怎么办呢,我当时的解决思路简单粗暴,把 gitea的配置文件和之前halo的写一块不就得了,直接使用 halo部署的 mysql数据库。OK,简单直接粗暴。

配置文件杂乱

过了一阵我又想搭建一个图床应用,使用的是比较主流的图床应用兰空图床,他也要配置一个数据库,这我可坐不住了,没道理的,配置文件写一块吧,显得 docker-compose.yml文件杂乱无章,不同的应用都部署到一块,不写吧,可是我又不想再 pull一个 mysql的镜像,我的服务器本就不富裕。

网上搜索无果的情况下(也可能是我搜索的姿势不对)。我去问了问百度的文心一言。还是有惊喜的。下面是文心一言的回答。

问:我已经使用docker安装了数据库,如何在其他的docker-compose文件如何使用已经部署好的数据库?

答:要在一个Docker Compose文件中连接到已经在另一个Docker Compose文件中运行的数据库,你可以通过定义链接或使用环境变量来实现。以下是两种方法:

  1. 使用链接:

假设你有两个Compose文件,一个用于数据库,另一个用于其他服务。

# docker-compose-db.yml
version: '3'
services:
  db:
    image: mysql:5.7
    container_name: db
    ports:
      - "3306:3306"
    environment:
      MYSQL_ROOT_PASSWORD: password
      MYSQL_DATABASE: mydb
      MYSQL_USER: myuser
      MYSQL_PASSWORD: mypass

对于其他服务,你可以在docker-compose.yml中链接到数据库服务:

# docker-compose.yml
version: '3'
services:
  web:
    image: nginx:latest
    container_name: web
    ports:
      - "8080:80"
    links:
      - db:db_host
    environment:
      DB_HOST: db_host
      DB_NAME: mydb
      DB_USER: myuser
      DB_PASSWORD: mypass
  1. 使用环境变量:

如果你不使用链接,你可以通过环境变量来传递数据库的连接信息。首先,在数据库的Compose文件中定义环境变量:

# docker-compose-db.yml
version: '3'
services:
  db:
    image: mysql:5.7
    container_name: db
    ports:
      - "3306:3306"
    environment:
      MYSQL_ROOT_PASSWORD: password
      MYSQL_DATABASE: mydb
      MYSQL_USER: myuser
      MYSQL_PASSWORD: mypass
    networks:
      - my_network

然后,在另一个Compose文件中,使用 external网络并连接到同一个网络:

# docker-compose.yml
version: '3'
services:
  web:
    image: nginx:latest
    container_name: web
    ports:
      - "8080:80"
    environment:
      DB_HOST: db_host
      DB_NAME: mydb
      DB_USER: myuser
      DB_PASSWORD: mypass
    networks:
      - my_network
networks:
  my_network:
    external: true

在上面的例子中,web服务会连接到 db服务所在的同一网络,并且可以从该服务中获取环境变量。这允许你在 web服务中连接到数据库。

讲道理,第一种方法我没有成功,但是第二种方法确确实实是可行的

我思考了一下,访问不到数据库的原因大概就是不在同一个网段内吧,按照第二种方法来讲,其实是把数据库和图床两个应用的网络放到了同一个网段,所以就可以访问到了。

额外的收获是还学会了docker的一个命令:docker inspect xxxxxxxxx | grep IPAdress

其中一串x的是容器的容器id,这样就可以查看某个容器被docker分配的ip地址了。


Comment