Windows环境下Docker执行bash脚本失败的原因及解决办法
问题原因
1. 换行符格式不兼容
Windows系统默认用CRLF(\r\n)作为文本换行符,而Docker容器内的Linux环境使用LF(\n)。如果startup.sh是在Windows下编辑的,换行符会是CRLF,容器内的Shell(如bash)执行时会把\r当成命令的一部分,导致出现./startup.sh: not found或执行报错。
2. 脚本执行权限丢失
Windows的NTFS文件系统不支持Linux的POSIX权限位(比如chmod +x赋予的执行权限)。在Windows环境构建镜像时,即使Dockerfile里加了RUN chmod +x startup.sh,也可能因文件共享的权限映射问题,导致容器内的脚本没有执行权限,无法直接运行。
3. Docker Desktop文件系统适配差异
Mac上的Docker基于Linux虚拟机,文件系统权限和格式更贴近Linux;而Windows上的Docker若用Hyper-V后端,文件共享时会做格式转换,可能破坏脚本可执行性;即使使用WSL2后端,未正确配置挂载也会出现权限或格式问题。
解决方法
方法一:统一脚本换行符为LF
- 在VS Code等编辑器中打开
startup.sh,右下角切换换行符为LF后保存,重新构建镜像。 - 或用Git工具转换:
重新拉取或保存脚本,Git会自动将换行符转为LF。git config --global core.autocrlf input
方法二:确保脚本拥有执行权限
在Dockerfile中拷贝脚本后,明确添加赋予执行权限的步骤:
COPY startup.sh . RUN chmod +x startup.sh CMD ["./startup.sh"]
这能保证容器内的脚本被赋予可执行权限,避免权限问题导致的执行失败。
方法三:指定脚本的Shell解释器
在startup.sh第一行添加正确的shebang,指定用bash执行:
#!/bin/bash uvicorn app.main:app --reload --workers 1 --host 0.0.0.0 --port 8000
避免因容器内默认Shell的差异引发执行问题。
方法四:切换Docker Desktop为WSL2后端(Windows环境)
若Windows机器支持WSL2,将Docker Desktop设置为WSL2后端,在WSL2的Linux环境下编辑脚本、构建镜像,文件格式和权限会与Linux环境完全一致,彻底规避跨系统兼容性问题。
方法五:直接使用exec格式命令替代脚本
如果不想处理脚本兼容性问题,可直接在CMD中指定uvicorn命令,跳过脚本执行环节:
CMD ["uvicorn", "app.main:app", "--reload", "--workers", "1", "--host", "0.0.0.0", "--port", "8000"]
内容的提问来源于stack exchange,提问作者writes_on

