22import shlex
33import subprocess
44import sys
5+ import shutil
56from pathlib import Path
67from rich .panel import Panel
78from rich .progress import Progress , SpinnerColumn , TextColumn
@@ -88,8 +89,10 @@ def _write_docker_compose(output_path):
8889 if not services :
8990 return None
9091
91- compose_lines = ["services:" ]
92+ compose_lines = ["networks:" , " concore-net:" , " driver: bridge" , "" , " services:" ]
9293
94+ prev_service_name = None
95+ named_volumes = set ()
9396 for index , service in enumerate (services , start = 1 ):
9497 service_name = re .sub (r"[^A-Za-z0-9_.-]" , "-" , service ["container_name" ]).strip (
9598 "-."
@@ -104,10 +107,30 @@ def _write_docker_compose(output_path):
104107 compose_lines .append (
105108 f" container_name: { _yaml_quote (service ['container_name' ])} "
106109 )
110+ compose_lines .append (" restart: on-failure" )
111+ compose_lines .append (" networks:" )
112+ compose_lines .append (" - concore-net" )
113+
114+ # Chain services sequentially to prevent ZMQ race conditions
115+ if prev_service_name :
116+ compose_lines .append (" depends_on:" )
117+ compose_lines .append (f" - { prev_service_name } " )
118+
107119 if service ["volumes" ]:
108120 compose_lines .append (" volumes:" )
109121 for volume_spec in service ["volumes" ]:
110122 compose_lines .append (f" - { _yaml_quote (volume_spec )} " )
123+ part1 = volume_spec .split (':' )[0 ]
124+ if re .match (r"^[a-zA-Z0-9_-]+$" , part1 ):
125+ named_volumes .add (part1 )
126+
127+ prev_service_name = service_name
128+
129+ if named_volumes :
130+ compose_lines .append ("" )
131+ compose_lines .append ("volumes:" )
132+ for v in sorted (named_volumes ):
133+ compose_lines .append (f" { v } :" )
111134
112135 compose_lines .append ("" )
113136 compose_path = output_path / "docker-compose.yml"
@@ -180,6 +203,27 @@ def build_workflow(
180203
181204 progress .update (task , completed = True )
182205
206+ if exec_type == "docker" :
207+ req_src = Path .cwd () / "requirements.txt"
208+ if not req_src .exists ():
209+ req_src = source_path / "requirements.txt"
210+ req_dest = output_path / "src" / "requirements.txt"
211+ if req_src .exists () and (output_path / "src" ).exists ():
212+ shutil .copy2 (req_src , req_dest )
213+ elif (output_path / "src" ).exists ():
214+ req_dest .touch ()
215+
216+ # Append requirement copying to generated scripts
217+ for s_name in ["build" , "build.bat" ]:
218+ s_path = output_path / s_name
219+ if s_path .exists ():
220+ content = s_path .read_text (encoding = "utf-8" )
221+ if s_name == "build" :
222+ content = content .replace ("docker build" , "cp ../src/requirements.txt .\n docker build" )
223+ else :
224+ content = content .replace ("docker build" , "copy ..\\ src\\ requirements.txt .\n docker build" )
225+ s_path .write_text (content , encoding = "utf-8" )
226+
183227 if result .stdout :
184228 console .print (result .stdout )
185229
0 commit comments