Dockerfile总结:常用指令、注意事项、常见错误(no such file or directory、Permission denied)

Dockerfile精讲

什么是 Dockerfile?

Dockerfile 是一个用来构建镜像的文本文件,文本内容包含了一条条构建镜像所需的指令和说明。


指令详解

点击参考:使用 Dockerfile 定制镜像

注意事项

  • RUN (docker镜像越来越大的原因之一)

    RUN <命令行命令> # <命令行命令> 等同于,在终端操作的 shell 命令。

    注意: Dockerfile 的指令每执行一次都会在 docker 上新建一层。所以过多无意义的层,会造成镜像膨胀过大。例如:

    FROM centos
    RUN yum install wget
    RUN wget -O redis.tar.gz "http://download.redis.io/releases/redis-5.0.3.tar.gz"
    RUN tar -xvf redis.tar.gz
    
    以上执行会创建 3 层镜像。可简化为以下格式:
    
    FROM centos
    RUN yum install wget \
        && wget -O redis.tar.gz "http://download.redis.io/releases/redis-5.0.3.tar.gz" \
        && tar -xvf redis.tar.gz
    

    如上,以 && 符号连接命令,这样执行后,只会创建 1 层镜像。

  • CMD

    作用:为启动的容器指定默认要运行的程序,

你遇到的错误信息: ``` /bin/sh: optionResult: Permission denied grep: optionResult: No such file or directory rm: cannot remove 'optionResult': No such file or directory Makefile:117: *** "openssl does not support zlib!". Stop. ``` 这通常出现在 **编译 OpenSSL 或某些依赖 OpenSSL 的项目(如 Nginx、cURL)时**,尤其是在自定义 `./configure` 和 `make` 流程中。 --- ## ✅ 错误解析 我们逐行分析: ```bash /bin/sh: optionResult: Permission denied ``` 👉 表示 shell 尝试执行或写入一个叫 `optionResult` 的文件/命令,但没有权限,或者它不是一个可执行文件。 ```bash grep: optionResult: No such file or directory rm: cannot remove 'optionResult': No such file or directory ``` 👉 说明脚本试图读取并删除 `optionResult`,但它根本不存在。 ```bash Makefile:117: *** "openssl does not support zlib!". Stop. ``` 👉 这是最终报错 —— 编译系统检测到:**OpenSSL 不支持 zlib 压缩**,所以中断构建。 --- ## 🔍 根源问题 这个错误一般出现在以下场景: ### 场景 1:你在交叉编译或手动配置 OpenSSL 你的 `Makefile` 或 `configure` 脚本尝试运行类似这样的测试代码来判断 OpenSSL 是否支持 zlib: ```bash echo "testing for zlib..." > optionResult ${CC} ${CFLAGS} -o test test.c -lzlib -lssl if grep -q "some_pattern" optionResult; then ... fi rm optionResult ``` 但由于: - 当前目录不可写(权限不足) - 或者临时文件名冲突(`optionResult` 是硬编码的临时文件) - 或者缺少头文件/库导致编译失败,没生成输出 → 导致 `optionResult` 没有被正确创建 → 后续 `grep` 和 `rm` 报错 → 最终误判为 “OpenSSL does not support zlib” --- ### 场景 2:你正在编译 Nginx 并启用 `--with-http_ssl_module --with-zlib` 等选项 Nginx 的 `auto/feature` 检测脚本会做如下操作: ```bash cat << EOF > $AUTOCONF_ERRFILE checking for zlib library ... found EOF # 然后调用: ngx_feature="zlib" ngx_feature_name="NGX_ZLIB" ngx_feature_run=yes ngx_feature_incs="#include <zlib.h>" ngx_feature_path= ngx_feature_libs="-lz" ngx_feature_test="z_stream z; z.zalloc = Z_NULL;" . auto/feature ``` 其中 `auto/feature` 内部使用一个叫 `$ngx_test_file` 或硬编码 `optionResult.c` / `optionResult` 的临时文件进行编译测试。 如果无法写入当前目录 → 创建失败 → 判断出错 → 报 `"openssl does not support zlib!"` --- ## ✅ 解决方案 ### ✅ 方案 1:确保当前目录可写 ```bash # 检查权限 ls -ld . # 如果不可写,修改权限 chmod +w . # 或切换到可写目录再编译 cd /tmp/build cp -r /path/to/source/* . ``` 然后重新运行 `./configure` 或 `make` --- ### ✅ 方案 2:设置 TMPDIR 环境变量(推荐) 很多 configure 脚本允许通过环境变量指定临时目录: ```bash export TMPDIR=/tmp mkdir -p $TMPDIR # 再次运行 configure/make make clean make ``` 这样就不会在当前目录生成 `optionResult` 文件了。 --- ### ✅ 方案 3:修复 Makefile 中的硬编码临时文件名 打开报错的 `Makefile`(第117行附近),找到类似: ```makefile @if ${CC} ${CFLAGS} ... ; then \ echo "yes"; \ else \ echo "no"; \ echo "openssl does not support zlib!"; \ false; \ fi ``` 或者查找: ```makefile optionResult ``` 将其改为使用安全路径的临时文件: ```makefile TEMP_FILE=$(shell mktemp) ``` 例如修改原逻辑为: ```makefile @if mktemp -d >/dev/null 2>&1; then \ TMPFILE=$$(mktemp); \ echo 'your test code' > $$TMPFILE.c && \ ${CC} $$TMPFILE.c -lz -lssl -o $$TMPFILE 2>/dev/null && \ rm -f $$TMPFILE $$TMPFILE.c && \ echo "zlib supported"; \ else \ echo "zlib not supported"; \ false; \ fi ``` --- ### ✅ 方案 4:显式禁用 zlib 支持(如果你不需要) 如果你并不需要压缩功能(比如 Nginx 的 `gzip on;`),可以关闭: #### 示例:Nginx 编译时去掉 zlib ```bash ./configure \ --without-http_gzip_module \ --with-http_ssl_module \ ... ``` 这样就不会触发对 zlib 的检测,跳过这个问题。 > ⚠️ 注意:生产环境一般需要 gzip,慎用此法。 --- ### ✅ 方案 5:安装缺失的 zlib 开发包(根本性解决) 即使文件能写,如果没有开发库也会导致测试失败。 #### Ubuntu/Debian: ```bash apt-get update apt-get install -y zlib1g-dev libssl-dev ``` #### CentOS/RHEL/Fedora: ```bash yum install -y zlib-devel openssl-devel # 或 dnf install -y zlib-devel openssl-devel ``` 然后重新编译。 --- ## ✅ 验证 zlib 和 OpenSSL 是否正常工作 写个简单测试程序: ```c // test_zlib_ssl.c #include <zlib.h> #include <openssl/ssl.h> #include <stdio.h> int main() { printf("zlib version: %s\n", zlibVersion()); SSL_library_init(); printf("OpenSSL initialized.\n"); return 0; } ``` 编译: ```bash gcc test_zlib_ssl.c -lz -lssl -lcrypto -o test ./test ``` ✅ 成功运行说明环境没问题。 --- ## ✅ 总结:你应该怎么做? | 步骤 | 操作 | |------|------| | 1️⃣ | 确保当前目录可写:`chmod +w .` | | 2️⃣ | 设置临时目录:`export TMPDIR=/tmp` | | 3️⃣ | 安装依赖:`zlib-dev`, `libssl-dev` | | 4️⃣ | 清理后重试:`make clean && make` | | 5️⃣ | 若仍不行,检查 Makefile 是否硬编码 `optionResult`,建议改用 `mktemp` | ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

szZack

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值