@@ -123,7 +123,7 @@ parse_arguments() {
123123detect_docker_compose () {
124124 local container_name=" $1 "
125125
126- # 方法1: 检查容器标签
126+ # 方法1: 检查容器标签(最准确的方法)
127127 local compose_project=$( docker inspect --format=' {{index .Config.Labels "com.docker.compose.project"}}' " ${container_name} " 2> /dev/null || echo " " )
128128 local compose_service=$( docker inspect --format=' {{index .Config.Labels "com.docker.compose.service"}}' " ${container_name} " 2> /dev/null || echo " " )
129129
@@ -132,37 +132,117 @@ detect_docker_compose() {
132132 return 0
133133 fi
134134
135- # 方法2: 检查容器名称模式 (project_service_number)
135+ # 方法2: 检查其他compose相关标签
136+ local compose_version=$( docker inspect --format=' {{index .Config.Labels "com.docker.compose.version"}}' " ${container_name} " 2> /dev/null || echo " " )
137+ local compose_config_files=$( docker inspect --format=' {{index .Config.Labels "com.docker.compose.config_files"}}' " ${container_name} " 2> /dev/null || echo " " )
138+
139+ if [[ -n " ${compose_version} " || -n " ${compose_config_files} " ]]; then
140+ # 尝试从容器名称推断项目和服务名
141+ if [[ " ${container_name} " =~ ^([a-zA-Z0-9_-]+)_([a-zA-Z0-9_-]+)_[0-9]+$ ]]; then
142+ local project=" ${BASH_REMATCH[1]} "
143+ local service=" ${BASH_REMATCH[2]} "
144+ echo " ${project} :${service} "
145+ return 0
146+ elif [[ " ${container_name} " =~ ^([a-zA-Z0-9_-]+)_([a-zA-Z0-9_-]+)$ ]]; then
147+ local project=" ${BASH_REMATCH[1]} "
148+ local service=" ${BASH_REMATCH[2]} "
149+ echo " ${project} :${service} "
150+ return 0
151+ fi
152+ fi
153+
154+ # 方法3: 检查容器名称模式(更宽松的匹配)
136155 if [[ " ${container_name} " =~ ^([a-zA-Z0-9_-]+)_([a-zA-Z0-9_-]+)_[0-9]+$ ]]; then
137156 local project=" ${BASH_REMATCH[1]} "
138157 local service=" ${BASH_REMATCH[2]} "
139158 echo " ${project} :${service} "
140159 return 0
160+ elif [[ " ${container_name} " =~ ^([a-zA-Z0-9_-]+)_([a-zA-Z0-9_-]+)$ ]]; then
161+ local project=" ${BASH_REMATCH[1]} "
162+ local service=" ${BASH_REMATCH[2]} "
163+ echo " ${project} :${service} "
164+ return 0
141165 fi
142166
143- # 方法3 : 检查网络名称
167+ # 方法4 : 检查网络名称(更全面的网络检测)
144168 local networks=$( docker inspect --format=' {{range $net, $conf := .NetworkSettings.Networks}}{{$net}} {{end}}' " ${container_name} " 2> /dev/null || echo " " )
145169 for network in ${networks} ; do
170+ # 检查常见的compose网络模式
146171 if [[ " ${network} " =~ ^([a-zA-Z0-9_-]+)_default$ ]]; then
147172 local project=" ${BASH_REMATCH[1]} "
148173 echo " ${project} :unknown"
149174 return 0
175+ elif [[ " ${network} " =~ ^([a-zA-Z0-9_-]+)_network$ ]]; then
176+ local project=" ${BASH_REMATCH[1]} "
177+ echo " ${project} :unknown"
178+ return 0
179+ elif [[ " ${network} " =~ ^([a-zA-Z0-9_-]+)_([a-zA-Z0-9_-]+)_network$ ]]; then
180+ local project=" ${BASH_REMATCH[1]} "
181+ local service=" ${BASH_REMATCH[2]} "
182+ echo " ${project} :${service} "
183+ return 0
150184 fi
151185 done
152186
187+ # 方法5: 检查容器的工作目录和挂载点
188+ local working_dir=$( docker inspect --format=' {{.Config.WorkingDir}}' " ${container_name} " 2> /dev/null || echo " " )
189+ if [[ -n " ${working_dir} " ]]; then
190+ # 检查工作目录是否包含compose相关路径
191+ if [[ " ${working_dir} " =~ /([a-zA-Z0-9_-]+)/? $ ]]; then
192+ local project=" ${BASH_REMATCH[1]} "
193+ # 尝试从容器名称提取服务名
194+ if [[ " ${container_name} " =~ ^.* _([a-zA-Z0-9_-]+)(_[0-9]+)? $ ]]; then
195+ local service=" ${BASH_REMATCH[1]} "
196+ echo " ${project} :${service} "
197+ return 0
198+ else
199+ echo " ${project} :unknown"
200+ return 0
201+ fi
202+ fi
203+ fi
204+
205+ # 方法6: 检查挂载点路径
206+ local mounts=$( docker inspect --format=' {{json .Mounts}}' " ${container_name} " 2> /dev/null || echo " []" )
207+ if [[ -n " ${mounts} " && " ${mounts} " != " []" ]]; then
208+ # 从挂载点路径推断项目名
209+ local mount_paths=$( echo " ${mounts} " | jq -r ' .[].Source' 2> /dev/null || echo " " )
210+ for mount_path in ${mount_paths} ; do
211+ if [[ " ${mount_path} " =~ /([a-zA-Z0-9_-]+)/[a-zA-Z0-9_-]+/? $ ]]; then
212+ local project=" ${BASH_REMATCH[1]} "
213+ # 检查这个项目是否真的有compose文件
214+ if find_docker_compose_files " ${project} " | grep -q . ; then
215+ if [[ " ${container_name} " =~ ^.* _([a-zA-Z0-9_-]+)(_[0-9]+)? $ ]]; then
216+ local service=" ${BASH_REMATCH[1]} "
217+ echo " ${project} :${service} "
218+ return 0
219+ else
220+ echo " ${project} :unknown"
221+ return 0
222+ fi
223+ fi
224+ fi
225+ done
226+ fi
227+
153228 return 1
154229}
155230
156231# 查找docker-compose文件
157232find_docker_compose_files () {
158233 local project_name=" $1 "
234+ local container_name=" $2 "
235+
159236 local search_paths=(
160237 " /opt"
161238 " /home"
162239 " /root"
163240 " /var/lib/docker/volumes"
164241 " /docker-compose"
165242 " /compose"
243+ " /app"
244+ " /srv"
245+ " /var/www"
166246 )
167247
168248 # 添加当前工作目录
@@ -173,20 +253,109 @@ find_docker_compose_files() {
173253 search_paths+=(" ${HOME} " )
174254 fi
175255
256+ # 从容器标签获取compose文件路径
257+ local compose_config_files=$( docker inspect --format=' {{index .Config.Labels "com.docker.compose.config_files"}}' " ${container_name} " 2> /dev/null || echo " " )
258+ if [[ -n " ${compose_config_files} " ]]; then
259+ local config_dir=$( dirname " ${compose_config_files} " )
260+ if [[ -d " ${config_dir} " ]]; then
261+ search_paths+=(" ${config_dir} " )
262+ fi
263+ fi
264+
265+ # 从容器工作目录推断
266+ local working_dir=$( docker inspect --format=' {{.Config.WorkingDir}}' " ${container_name} " 2> /dev/null || echo " " )
267+ if [[ -n " ${working_dir} " && " ${working_dir} " != " /" ]]; then
268+ local work_dir_parent=$( dirname " ${working_dir} " )
269+ if [[ -d " ${work_dir_parent} " ]]; then
270+ search_paths+=(" ${work_dir_parent} " )
271+ fi
272+ fi
273+
274+ # 从挂载点推断
275+ local mounts=$( docker inspect --format=' {{json .Mounts}}' " ${container_name} " 2> /dev/null || echo " []" )
276+ if [[ -n " ${mounts} " && " ${mounts} " != " []" ]]; then
277+ local mount_paths=$( echo " ${mounts} " | jq -r ' .[].Source' 2> /dev/null || echo " " )
278+ for mount_path in ${mount_paths} ; do
279+ if [[ -d " ${mount_path} " ]]; then
280+ local mount_parent=$( dirname " ${mount_path} " )
281+ if [[ -d " ${mount_parent} " ]]; then
282+ search_paths+=(" ${mount_parent} " )
283+ fi
284+ fi
285+ done
286+ done
287+
176288 local compose_files=()
289+ local found_files=()
290+
291+ # 去重搜索路径
292+ local unique_paths=()
293+ for path in " ${search_paths[@]} " ; do
294+ if [[ -d " ${path} " ]]; then
295+ local is_duplicate=false
296+ for existing_path in " ${unique_paths[@]} " ; do
297+ if [[ " ${path} " == " ${existing_path} " ]]; then
298+ is_duplicate=true
299+ break
300+ fi
301+ done
302+ if [[ " ${is_duplicate} " == false ]]; then
303+ unique_paths+=(" ${path} " )
304+ fi
305+ fi
306+ done
177307
178- for search_path in " ${search_paths[@]} " ; do
179- if [[ -d " ${search_path} " ]]; then
180- # 查找包含项目名称的目录
181- while IFS= read -r -d ' ' dir; do
182- # 检查常见的docker-compose文件名
183- for compose_file in " docker-compose.yml" " docker-compose.yaml" " compose.yml" " compose.yaml" ; do
184- if [[ -f " ${dir} /${compose_file} " ]]; then
308+ # 按优先级搜索
309+ for search_path in " ${unique_paths[@]} " ; do
310+ # 1. 精确匹配项目名称的目录
311+ if [[ -d " ${search_path} /${project_name} " ]]; then
312+ for compose_file in " docker-compose.yml" " docker-compose.yaml" " compose.yml" " compose.yaml" ; do
313+ if [[ -f " ${search_path} /${project_name} /${compose_file} " ]]; then
314+ compose_files+=(" ${search_path} /${project_name} /${compose_file} " )
315+ found_files+=(" ${compose_file} " )
316+ fi
317+ done
318+ fi
319+
320+ # 2. 在搜索路径中查找包含项目名称的目录
321+ while IFS= read -r -d ' ' dir; do
322+ for compose_file in " docker-compose.yml" " docker-compose.yaml" " compose.yml" " compose.yaml" ; do
323+ if [[ -f " ${dir} /${compose_file} " ]]; then
324+ # 检查是否已经找到这个文件
325+ local is_duplicate=false
326+ for found_file in " ${found_files[@]} " ; do
327+ if [[ " ${compose_file} " == " ${found_file} " ]]; then
328+ is_duplicate=true
329+ break
330+ fi
331+ done
332+ if [[ " ${is_duplicate} " == false ]]; then
185333 compose_files+=(" ${dir} /${compose_file} " )
334+ found_files+=(" ${compose_file} " )
186335 fi
187- done
188- done < <( find " ${search_path} " -maxdepth 3 -type d -name " *${project_name} *" -print0 2> /dev/null || true)
189- fi
336+ fi
337+ done
338+ done < <( find " ${search_path} " -maxdepth 3 -type d -name " *${project_name} *" -print0 2> /dev/null || true)
339+
340+ # 3. 在搜索路径根目录查找compose文件
341+ for compose_file in " docker-compose.yml" " docker-compose.yaml" " compose.yml" " compose.yaml" ; do
342+ if [[ -f " ${search_path} /${compose_file} " ]]; then
343+ # 检查文件内容是否包含项目名称
344+ if grep -q " ${project_name} " " ${search_path} /${compose_file} " 2> /dev/null; then
345+ local is_duplicate=false
346+ for found_file in " ${found_files[@]} " ; do
347+ if [[ " ${compose_file} " == " ${found_file} " ]]; then
348+ is_duplicate=true
349+ break
350+ fi
351+ done
352+ if [[ " ${is_duplicate} " == false ]]; then
353+ compose_files+=(" ${search_path} /${compose_file} " )
354+ found_files+=(" ${compose_file} " )
355+ fi
356+ fi
357+ fi
358+ done
190359 done
191360
192361 echo " ${compose_files[@]} "
@@ -417,7 +586,7 @@ backup_compose_files() {
417586 local service_name=$( echo " ${compose_info} " | cut -d: -f2)
418587
419588 # 查找docker-compose文件
420- local compose_files=($( find_docker_compose_files " ${project_name} " ) )
589+ local compose_files=($( find_docker_compose_files " ${project_name} " " ${container_name} " ) )
421590
422591 if [[ ${# compose_files[@]} -gt 0 ]]; then
423592 log_info " 找到 ${# compose_files[@]} 个docker-compose文件"
0 commit comments