如何在多个Docker Compose组之间共享单个Docker数据库服务?

huangapple go评论104阅读模式
英文:

How to share a single Docker database service across multiple Docker Compose groups?

问题

我有一个包括Web服务器和Oracle数据库的Docker Compose组。我只在开发环境中使用它,不用于生产环境。 Web服务器依赖于Oracle,因此在启动之前会等待Oracle。

version: '3.9'

services:
  frontend:
    image: "${FRONTEND_IMAGE_TAG}"
    env_file:
      - .env
    volumes:
      - .:/var/www/
    ports:
      - ${httpsport}
    restart: always  
    depends_on: 
      oracle:
          condition: service_healthy      

  oracle:
    image: container-registry.oracle.com/database/enterprise:${ORACLE_VERSION}
    env_file:
      - .env
    ports:
      - ${ORACLE_LISTEN_PORT}:1521
      - ${ORACLE_TCPS_PORT}:2484
      - ${ORACLE_EM_PORT}:5500
    volumes:
      - ${ORACLE_ORADATA}:/opt/oracle/oradata
      - ${ORACLE_TRANSFER}:/opt/oracle/transfer

只要我只运行组的单个实例,它就可以很好地工作。但在开发过程中,我经常希望运行多个开发组,例如:

cd /web/dev
docker compose up -d

cd /web/test
docker compose up -d

这里的问题是它将尝试运行第二个Oracle数据库,我绝对不希望这种情况发生,因为我正在使用卷来持久化数据(而且似乎对机器产生了不必要的大负载)。我只想运行一次Oracle Docker容器,并在任何第二次和随后尝试运行我的Compose组时共享它。

一些我正在考虑的方法:

  • 使用Docker Network将Oracle拆分成自己的服务。然后我将不得不找出一种方法来检查Oracle服务是否已启动,并在它没有运行时启动它等等。似乎不清楚这将如何工作。

  • 使用Docker Compose extends来拆分Oracle。我认为这将具有与之前方法相同的问题。

  • 可能编写一些Shell脚本来执行检查并启动Oracle服务。我不喜欢这样做,因为感觉Docker应该有一个内置的解决方案。

有一个GitHub问题,许多人要求Docker添加这个功能。在那个问题得到更新之前,我很愿意听听一些解决方法。

英文:

I have a Docker Compose group consisting of a web server and an Oracle database. I use this for development only, not in production. The web server depends_on Oracle and so waits for Oracle before it starts up.

version: '3.9'

services:
  frontend:
    image: "${FRONTEND_IMAGE_TAG}"
    env_file:
      - .env
    volumes:
      - .:/var/www/
    ports:
      - ${httpsport}
    restart: always  
    depends_on: 
      oracle:
          condition: service_healthy      

  oracle:
    image: container-registry.oracle.com/database/enterprise:${ORACLE_VERSION}
    env_file:
      - .env
    ports:
      - ${ORACLE_LISTEN_PORT}:1521
      - ${ORACLE_TCPS_PORT}:2484
      - ${ORACLE_EM_PORT}:5500
    volumes:
      - ${ORACLE_ORADATA}:/opt/oracle/oradata
      - ${ORACLE_TRANSFER}:/opt/oracle/transfer

It works very well as long as I only run a single instance of my group. But often during development, I'd like to run multiple development groups e.g.

cd /web/dev
docker compose up -d

cd /web/test
docker compose up -d

The problem here is that it will attempt to run a 2nd Oracle database, which I absolutely do not want to happen, as I'm using a volume to persist data (plus it seems like a big unnecessary load on the machine). I only want to run the Oracle Docker container once and share it among any 2nd and subsequent attempts to run my Compose group.

Some approaches I'm considering:

  • use Docker Network to split out Oracle into its own service. Then I'd have to figure out a way to check if the Oracle service was up and running, and start it when it's not etc. Seems unclear how this would work

  • use Docker Compose extends to split out Oracle. I think this will have the same problems as previous approach

  • maybe write some shell script to do the checks and start Oracle service. I don't like doing this though, it feels like Docker should have a in-built solution

There is a Github issue with many people requesting this feature
from Docker. Until that gets updated I'd love to hear some
workarounds.

答案1

得分: 0

这是您要翻译的内容:

In the end I wrote a shell script to manage this. I split my Docker Compose file into 2 files, one for Oracle running on its own network, and one for the front end. The shell script checks that Oracle is up and healthy before starting the front end.

oracle.yaml looks like this:

version: '3.9'

networks:
  mynetwork:

services:
  oracle:
    image: container-registry.oracle.com/database/enterprise:${ORACLE_VERSION}
    env_file:
      - .env
    ports:
      - ${ORACLE_LISTEN_PORT}:1521
      - ${ORACLE_TCPS_PORT}:2484
      - ${ORACLE_EM_PORT}:5500
    volumes:
      - ${ORACLE_ORADATA}:/opt/oracle/oradata
      - ${ORACLE_TRANSFER}:/opt/oracle/transfer
    networks:
      - mynetwork

and the frontend one looks like this:

version: '3.9'

services:
  frontend:
    image: "${FRONTEND_IMAGE_TAG}"
    env_file:
      - .env
    volumes:
      - .:/var/www/
    ports:
      - ${httpsport}
    restart: always 

Here's the shell script:

#!/bin/bash
# This script can be used to share an Oracle Docker instance with multiple Docker front end containers
# It checks if an Oracle Docker instance is running, starts it if necessary, then starts a frontend Docker instance
# This script must be run from the same directory as your docker-compose.yaml and oracle.yaml files

echo "Checking for a running Oracle Docker process..."

# Check if there is already a healthy Oracle Docker process running
docker_ps_output=$(docker ps --filter "name=oracle" --filter "health=healthy" | sed '1d')
if [[ -n $docker_ps_output ]]; then
    echo "Oracle is running. Starting frontend Docker container."
else
    echo "No healthy Oracle Docker process found. Starting Oracle Docker container now."

    # Start the Oracle Docker process
    docker compose -f oracle.yaml up -d

    # Loop until a healthy Oracle Docker process is found
    while true; do
        docker_ps_output=$(docker ps --filter "name=oracle" --filter "health=healthy" | sed '1d')
        if [[ -n $docker_ps_output ]]; then
            echo "Oracle Docker process is healthy. Starting frontend Docker container."
            break
        else
            echo "Oracle Docker process is not yet healthy. Continuing to check..."
            sleep 5
        fi
    done
fi

# Start our frontend Docker container (ignore warnings about removing orphans)
export COMPOSE_IGNORE_ORPHANS=True
docker compose up -d   
echo "frontend is starting" 
英文:

In the end I wrote a shell script to manage this. I split my Docker Compose file into 2 files, one for Oracle running on its own network, and one for the front end. The shell script checks that Oracle is up and healthy before starting the front end.

oracle.yaml looks like this:

version: '3.9'

networks:
  mynetwork:
    
services:
  oracle:
    image: container-registry.oracle.com/database/enterprise:${ORACLE_VERSION}
    env_file:
      - .env
    ports:
      - ${ORACLE_LISTEN_PORT}:1521
      - ${ORACLE_TCPS_PORT}:2484
      - ${ORACLE_EM_PORT}:5500
    volumes:
      - ${ORACLE_ORADATA}:/opt/oracle/oradata
      - ${ORACLE_TRANSFER}:/opt/oracle/transfer
    networks:
      - mynetwork

and the frontend one looks like this:

version: '3.9'

services:
  frontend:
    image: "${FRONTEND_IMAGE_TAG}"
    env_file:
      - .env
    volumes:
      - .:/var/www/
    ports:
      - ${httpsport}
    restart: always 

Here's the shell script:

#!/bin/bash
# This script can be used to share an Oracle Docker instance with multiple Docker front end containers
# It checks if an Oracle Docker instance is running, starts it if necessary, then starts a frontend Docker instance
# This script must be run from the same directory as your docker-compose.yaml and oracle.yaml files

echo "Checking for a running Oracle Docker process..."

# Check if there is already a healthy Oracle Docker process running
docker_ps_output=$(docker ps --filter "name=oracle" --filter "health=healthy" | sed '1d')
if [[ -n $docker_ps_output ]]; then
    echo "Oracle is running. Starting frontend Docker container."
else
    echo "No healthy Oracle Docker process found. Starting Oracle Docker container now."

    # Start the Oracle Docker process
    docker compose -f oracle.yaml up -d

    # Loop until a healthy Oracle Docker process is found
    while true; do
        docker_ps_output=$(docker ps --filter "name=oracle" --filter "health=healthy" | sed '1d')
        if [[ -n $docker_ps_output ]]; then
            echo "Oracle Docker process is healthy. Starting frontend Docker container."
            break
        else
            echo "Oracle Docker process is not yet healthy. Continuing to check..."
            sleep 5
        fi
    done
fi

# Start our frontend Docker container (ignore warnings about removing orphans)
export COMPOSE_IGNORE_ORPHANS=True
docker compose up -d   
echo "frontend is starting"   

huangapple
  • 本文由 发表于 2023年8月10日 19:58:22
  • 转载请务必保留本文链接:https://go.coder-hub.com/76875555.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定