运行Docker容器时遇Syntax error: "(" unexpected错误排查求助
/bin/sh: 2: Syntax error: "(" unexpected 原因分析与修复 问题描述
我编写了用于部署PaperMC的Dockerfile,镜像构建过程无报错,但启动容器时出现错误:
/bin/sh: 2: Syntax error: "(" unexpected
原本预期会出现未接受EULA的Java错误,想请教该问题的原因。
我的Dockerfile
# Setup Inst FROM ubuntu:latest MAINTAINER test LABEL maintainer="test" RUN mkdir /srv/papermc WORKDIR /srv/papermc # Install OpenJDK-17 RUN apt-get update && \ apt-get install -y openjdk-17-jre-headless && \ apt-get install -y ant && \ apt-get install -y screen && \ apt-get install -y wget && \ apt-get clean; # Fix certificate issues RUN apt-get update && \ apt-get install ca-certificates-java && \ apt-get clean && \ update-ca-certificates -f; # Setup JAVA_HOME -- useful for docker commandline ENV JAVA_HOME /usr/lib/jvm/java-17-openjdk-amd64/ RUN export JAVA_HOME # Download PAPERMINECRAFT RUN wget https://api.papermc.io/v2/projects/paper/versions/1.19.3/builds/363/downloads/paper-1.19.3-363.jar # STOP STOPSIGNAL SIGTERM # ENV ENV TYPE=VANILLA VERSION=1.19.3 EULA="" UID=1000 GID=1000 RCON_PASSWORD=paper # Prepare RUN EXPOSE 25565 25575 VOLUME /srv/papermc RUN echo "screen -AmdS minecraft java -Xms1024M -Xmx1024M -jar /srv/mcvanilla/paper-1.19.2-220.jar nogui" > start RUN chmod -R 775 /srv/papermc ENTRYPOINT ["/bin/sh"] CMD start HEALTHCHECK none
启动报错信息
Successfully tagged papermc:latest root@docker3:~# docker run papermc /bin/sh: 2: Syntax error: "(" unexpected
原因分析
VOLUME覆盖了启动脚本:你声明了
VOLUME /srv/papermc,而构建时生成的start脚本正好在这个目录下。启动容器时,Docker会自动创建匿名卷挂载到该目录,直接覆盖容器内原有的start脚本。此时执行/bin/sh start,shell找不到指定的脚本文件,可能误将start作为命令解析,从而引发语法错误。启动脚本中的路径错误:你下载的PaperMC jar包是
/srv/papermc/paper-1.19.3-363.jar,但start脚本里写的是/srv/mcvanilla/paper-1.19.2-220.jar,不仅版本不匹配,目标目录也不存在。不过这会导致"找不到jar包"的错误,不是当前的语法错误,但也是需要修复的问题。ENTRYPOINT与CMD的组合不合理:使用
ENTRYPOINT ["/bin/sh"]加CMD start的方式,相当于执行/bin/sh start,这种间接调用方式容易引发解析问题,不如直接指定启动命令更可靠。
修复方案
1. 解决VOLUME覆盖问题
如果不需要将/srv/papermc作为数据卷挂载,直接删除Dockerfile中的VOLUME /srv/papermc行;如果需要保留卷,将start脚本放到卷外的目录,比如/opt,修改相关构建命令:
RUN echo "screen -AmdS minecraft java -Xms1024M -Xmx1024M -jar /srv/papermc/paper-1.19.3-363.jar nogui" > /opt/start RUN chmod +x /opt/start CMD ["/opt/start"]
2. 修正启动脚本的jar路径
将start脚本中的jar路径改为正确的/srv/papermc/paper-1.19.3-363.jar,保证版本和路径一致。
3. 优化启动命令写法
方式一:给脚本添加shebang并直接启动
给start脚本添加shell解释器声明,然后直接作为CMD执行:
RUN echo "#!/bin/sh" > start RUN echo "screen -AmdS minecraft java -Xms1024M -Xmx1024M -jar /srv/papermc/paper-1.19.3-363.jar nogui" >> start RUN chmod +x start CMD ["./start"]
方式二:直接在CMD中指定命令(无需生成脚本)
跳过生成start脚本的步骤,直接在CMD中定义启动命令:
CMD ["screen", "-AmdS", "minecraft", "java", "-Xms1024M", "-Xmx1024M", "-jar", "/srv/papermc/paper-1.19.3-363.jar", "nogui"]
方式三:移除screen(更适合Docker场景)
Docker容器本身可以托管进程,不需要额外的screen,直接启动Java命令更便于日志排查:
CMD ["java", "-Xms1024M", "-Xmx1024M", "-jar", "/srv/papermc/paper-1.19.3-363.jar", "nogui"]
4. 清理多余命令
删除RUN export JAVA_HOME行,因为ENV指令已经设置了JAVA_HOME,容器启动时会自动加载该环境变量,构建时的export毫无意义。
内容的提问来源于stack exchange,提问作者KsBs

