docker run报错cannot execute binary file解决办法
背景说明
在执行如下命令时,报错:/bin/bash: /bin/bash: cannot execute binary file
。
docker run --rm -it registry.xxx.com/name/myimage:v1 /bin/bash /mydir/test.sh
- 镜像来源说明:
# 已有一个镜像压缩包:myimage_v1.tar.gz,加载:
docker load -i /tmp/myimage_v1.tar.gz
# 镜像地址加载后: registry.aaa.com/name/myimage:v1
# 当前使用镜像地址是:registry.xxx.com/name/myimage:v1 (aaa地址没有管理权限)
# 为了后面推送镜像到xxx地址,增加tag
docker tag registry.aaa.com/name/myimage:v1 registry.xxx.com/name/myimage:v1
- 报错问题排查
# 使用sh, /bin/sh, /bin/bash 执行均报错:cannot execute binary file
docker run --rm -it registry.xxx.com/name/myimage:v1 /bin/bash
# 使用python也同样报错: cannot execute binary file
docker run --rm -it registry.xxx.com/name/myimage:v1 python
# 使用R没有报错,可进行R命令行
docker run --rm -it registry.xxx.com/name/myimage:v1 R
通过DeepSeek查询提出了一些解决方式,测试还是没有解决。
但是其中提到可能是入口点(Entrypoint)或命令(CMD)配置
问题。
解决办法
方法1:设置入口点
docker run --entrypoint /bin/bash -t registry.xxx.com/name/myimage:v1 /mydir/test.sh
docker run --entrypoint python -t registry.xxx.com/name/myimage:v1 /mydir/mytest.py
方法2:修改Dockerfile(还是有问题)
若无法修改原Dockerfile,新建Dockerfile内容如下:
FROM registry.xxx.com/name/myimage:v1
ENTRYPOINT [ "/bin/bash", "-l", "-c" ]
然后再使用创建命令:
docker build -t registry.xxx.com/name/myimage:v1.1 .
测试有问题:
# 测试shell有问题:
# docker run -t registry.xxx.com/name/myimage:v1.1 /bin/bash /mydir/test.sh # 头部: #!/bin/bash
# 测试python脚本也有问题
# docker run -t registry.xxx.com/name/myimage:v1.1 python /mydir/mytest.py
测试没问题:
# chmod +x /mydir/test.sh, 直接执行可以
docker run -t registry.xxx.com/name/myimage:v1.1 /mydir/test.sh # 头部: #!/bin/bash
# 加"双引号",视为 /bin/bash -l -c "python /mydir/mytest.py"执行
docker run -t registry.xxx.com/name/myimage:v1.1 "python /mydir/mytest.py"
# 但是 直接进入镜像时有报错提示:/bin/bash: -c: option requires an argument
docker run --rm -it registry.xxx.com/name/myimage:v1.1
# 需要加:"/bin/bash" 执行的参数才能进入
docker run --rm -it registry.xxx.com/name/myimage:v1.1 "/bin/bash"
注:一开始直接使用了原来的aaa
地址(registry.aaa.com/name/myimage:v1)创建Dockerfile时发现无法获取,然后有docker tag新加了tag是xxx
地址(registry.xxx.com/name/myimage:v1)就可以创建了。
常用命令
# 详细的配置方式, json格式(参考:https://segmentfault.com/q/1010000042805131#)
docker inspect xxx:tag
# 查看所有历史层级的操作
docker history
# 构建镜像
docker build -t xxx:tag . # 当前目录下有文件Dockerfile
# docker build -t my-image:tag /path/to/dockerfile/dir # Dockerfile在特定目录下
# 推送镜像
docker push my-image:tag
# 打包镜像:
docker save -o xxximage.tar xxx:tag
# 加载镜像
docker load -i xxximage.tar
# 从远程Git仓库构建镜像,参考:https://zhuanlan.zhihu.com/p/665597873
docker build -t my-image:tag https://github.com/username/repo.git
# 删除镜像:
docker image rm <IMAGE ID>
# 检查容器日志:
docker logs <容器ID>
# 删除镜像:
docker image rm xxx:tag
# 无法删除报错: * could not remove image .. as it is being used by 1 containers: image is being used
# 查看所有运行中和运行过的容器
docker ps -a
# 停止运行过的容器ID或NAMES
docker stop [容器ID或NAMES]
# 删除容器
docker rm [容器ID或NAMES]
# 然后删除对应镜像
docker image rm xxx:tag
如何根据镜像获取dockerfile? dfimage
参考:https://cloud.tencent.com/developer/article/1828945
https://github.com/alpine-docker/dfimage
dfimage是一个alpine的镜像,启动的时候,通过将docker.sock映射到容器内部来运行,通常将这个操作做成别名
# 相当于:启动一个容器工具,执行完之后即删除
alias dfimage="docker run -v /var/run/docker.sock:/var/run/docker.sock --rm alpine/dfimage"
dfimage -sV=1.36 nginx:latest
获取docker file:
dfimage xxx:tag
其他
修改镜像文件
不推荐这种修改方式:过程比较黑盒子。
# 进入镜像,同时挂载路径/path
docker run -it -v /path:/path <image_name> /bin/bash
# 进入镜像后,找到要修改的文件
cd /path/file.txt
vi file.txt # 修改
# 退出
exit
# 将修改后的容器保存为一个新的镜像:
docker commit -a "镜像作者" -m "debug file.txt" <container_id> <new_image_name>
# example
docker commit -a "abc" -m "debug file.txt" a404c6c174a2 mymysql:v1
# 查看创建的镜像:
docker images
docker images mymysql:v1
参考博客: Docker 创建镜像、修改、上传镜像
示例Dockfile
FROM registry.xxx.aliyuncs.com/xxx/abc:v1.0
COPY file1 /path/file1
RUN rm -rf /path/mydir
WORKDIR /mydir
CMD ["/bin/bash"]