Oracle 12c Docker镜像制作:自定义tnsnames.ora配置报错求助
嘿,我来帮你捋清楚这个问题~你遇到的rm: cannot remove '/u01/app/oracle/product': Is a directory错误,大概率是你用的Oracle基础镜像里的ONBUILD指令在搞鬼,跟你的COPY操作直接相关。
为什么会出现这个错误?
很多官方或第三方的Oracle 12c Docker镜像会在Dockerfile里加入ONBUILD指令,这些指令会在你基于该镜像构建自己的镜像时自动执行。比如有些镜像会在ONBUILD里包含清理、初始化Oracle目录的脚本,当你执行COPY tnsnames.ora到/u01/app/oracle/product/12.1.0/xe/network/admin/路径时,会触发这些ONBUILD脚本,而脚本里可能写了错误的rm命令——比如试图用rm直接删除一个目录(不加-r参数的话,rm没法删除目录,就会报你看到的错误)。
另外还有个小概率原因:你COPY文件的路径权限不对,/u01/app/oracle/product目录属于oracle用户,而你用root用户COPY文件后,后续镜像的初始化脚本切换到oracle用户时,操作目录出现权限冲突,但这个不是主要诱因。
怎么解决?
这里给你几个实用的方案,按推荐程度排序:
1. 改用启动时复制文件(最稳妥)
避开构建时的ONBUILD触发问题,把tnsnames.ora先复制到临时目录,然后写一个启动脚本,在容器启动时再把文件复制到目标路径,同时启动Oracle服务。
修改后的Dockerfile示例:
# 假设你用的基础镜像是oracle/database:12c-xe FROM oracle/database:12c-xe # 把自定义tnsnames.ora复制到临时目录 COPY tnsnames.ora /tmp/ # 复制自定义启动脚本 COPY start_oracle.sh /u01/app/oracle/ # 给启动脚本加执行权限 RUN chmod +x /u01/app/oracle/start_oracle.sh # 设置容器启动时执行脚本 CMD ["/u01/app/oracle/start_oracle.sh"]
start_oracle.sh脚本内容:
#!/bin/bash # 复制tnsnames.ora到目标路径,同时设置正确的权限 cp /tmp/tnsnames.ora /u01/app/oracle/product/12.1.0/xe/network/admin/ chown oracle:oinstall /u01/app/oracle/product/12.1.0/xe/network/admin/tnsnames.ora # 启动Oracle服务 /etc/init.d/oracle-xe start # 保持容器运行(否则启动后会立刻退出) tail -f /u01/app/oracle/diag/rdbms/xe/XE/trace/alert_XE.log
2. 检查基础镜像的路径是否正确
有时候可能是你写的目标路径不对,比如有些Oracle 12c镜像的安装路径不是/u01/app/oracle/product/12.1.0/xe,而是/u01/app/oracle/product/12.1.0/dbhome_1。你可以先运行基础镜像,进入容器确认路径:
docker run -it --rm 你的基础镜像名 /bin/bash # 进入后执行以下命令查看路径 ls -l /u01/app/oracle/product/12.1.0/
如果路径不对,修正COPY指令里的目标路径即可。
3. 清理基础镜像的ONBUILD指令(不推荐)
如果上面的方法都不行,你可以重新构建一个去掉ONBUILD指令的基础镜像,但这个步骤比较繁琐,适合有一定Docker基础的用户:
- 先运行基础镜像,把容器提交为一个新镜像:
docker run -d --rm 你的基础镜像名 sleep 3600,然后获取容器ID,执行docker commit 容器ID my-oracle-12c-base - 用
docker inspect my-oracle-12c-base查看是否还有ONBUILD指令,确认没有后,再基于这个新镜像构建你的自定义镜像。
额外提醒
COPY完文件后,一定要给文件设置正确的权限(chown oracle:oinstall),因为Oracle服务是用oracle用户运行的,如果文件是root权限,Oracle进程可能读取不到tnsnames.ora,导致连接失败。
内容的提问来源于stack exchange,提问作者S. Wens

