英文:
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"
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论