上一篇使用runc与oci-image-tool运行容器中虽然成功使用
runc
运行起来了容器,但遇到了不少问题。本文再次讲述使用runc运行alpine linux容器,并解决上一次出现的相关问题。
注: 本文命令均在Ubuntu 18.04x64下运行通过
下载 解压镜像
skopeo与oci-image-tool分别用来下载与解压镜像,Ubuntu上两个工具需要从源码编译安装,而且需要提前配置好Go语言环境。
- 使用
skopeo copy docker://alpine:latest oci:alpine
下载镜像,skopeo的安装与使用参考Skopeo-Github,运行结果eric@ubuntu:~/images_tmp$ skopeo copy docker://alpine:latest oci:alpine Getting image source signatures Copying blob 89d9c30c1d48 done Copying config 759e71f0d3 done Writing manifest to image destination Storing signatures
- 使用
oci-image-tool create --ref platform.os=linux alpine alpine-bundle
制作符合OCI规范的镜像,oci-image-tool的安装与使用参考image-tools Github
rootfs为根文件系统,eric@ubuntu:~/images_tmp$ ls -l alpine-bundle/ total 8 -rw-rw-r-- 1 eric eric 217 Nov 9 11:51 config.json drwxr-x--- 19 eric eric 4096 Nov 9 11:51 rootfs
config.json
为符合runtime-spec
的配置文件
配置 运行
注: 此处要运行的是具有root权限的容器,因此不创建新的User Namespace
已知信息
-
capabilities权限信息: 容器必须具有权限去执行操作,config.json文件中可以现在容器内部权限
-
mount挂载信息: 系统级容器需要挂载必备的文件系统,如
proc sys cgroup
等 -
文件系统中目录、文件的可读可执行权限: 从根目录到容器文件系统内的所有文件夹,以及文件系统内的所有文件/文件夹(
/home/.../alpine-bundle/rootfs/*
)需要至少具有rwxrwxr-x(775)权限,否则可能会遇到各种各样的permission denied
,可以参考Can’t change to home directory, unable-to-su-with-root-bin-bash-permission-denied的第二个回答
具体过程
-
删除image-tool生成的
config.json
,该json文件缺少必要的mount、capabilities等信息 -
使用
runc spec
命令生成一个新的config.json
文件,关于runc的使用,参考runc-Github -
修改
config.json
文件,如下为修改完后的文件,参考rumtime-spec:{ "ociVersion": "1.0.1-dev", "process": { "terminal": true, "user": { "uid": 0, "gid": 0 }, "args": [ "/bin/ash" ], "env": [ "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" ], "cwd": "/", "capabilities": { "bounding": [ "CAP_AUDIT_WRITE", "CAP_KILL", "CAP_NET_BIND_SERVICE", "CAP_SETUID", "CAP_SETGID", "CAP_CHOWN", "CAP_SYS_ADMIN", "CAP_SETFCAP", "CAP_SETPCAP", "CAP_FOWNER" ], "effective": [ "CAP_AUDIT_WRITE", "CAP_KILL", "CAP_NET_BIND_SERVICE", "CAP_SETUID", "CAP_SETGID", "CAP_CHOWN", "CAP_SYS_ADMIN", "CAP_SETFCAP", "CAP_SETPCAP", "CAP_FOWNER" ], "inheritable": [ "CAP_AUDIT_WRITE", "CAP_KILL", "CAP_NET_BIND_SERVICE", "CAP_SETUID", "CAP_SETGID", "CAP_CHOWN", "CAP_SYS_ADMIN", "CAP_SETFCAP", "CAP_SETPCAP", "CAP_FOWNER" ], "permitted": [ "CAP_AUDIT_WRITE", "CAP_KILL", "CAP_NET_BIND_SERVICE", "CAP_SETUID", "CAP_SETGID", "CAP_CHOWN", "CAP_SYS_ADMIN", "CAP_SETFCAP", "CAP_SETPCAP", "CAP_FOWNER" ], "ambient": [ "CAP_AUDIT_WRITE", "CAP_KILL", "CAP_NET_BIND_SERVICE", "CAP_SETUID", "CAP_SETGID", "CAP_CHOWN", "CAP_SYS_ADMIN", "CAP_SETFCAP", "CAP_SETPCAP", "CAP_FOWNER" ] } }, "root": { "path": "rootfs", "readonly": false }, "mounts": [ { "destination": "/proc", "type": "proc", "source": "proc" }, { "destination": "/dev", "type": "tmpfs", "source": "tmpfs", "options": [ "nosuid", "strictatime", "mode=755", "size=65536k" ] }, { "destination": "/dev/pts", "type": "devpts", "source": "devpts", "options": [ "nosuid", "noexec", "newinstance", "ptmxmode=0666", "mode=0620", "gid=5" ] }, { "destination": "/dev/shm", "type": "tmpfs", "source": "shm", "options": [ "nosuid", "noexec", "nodev", "mode=1777", "size=65536k" ] }, { "destination": "/dev/mqueue", "type": "mqueue", "source": "mqueue", "options": [ "nosuid", "noexec", "nodev" ] }, { "destination": "/sys", "type": "sysfs", "source": "sysfs", "options": [ "nosuid", "noexec", "nodev", "ro" ] }, { "destination": "/sys/fs/cgroup", "type": "cgroup", "source": "cgroup", "options": [ "nosuid", "noexec", "nodev", "relatime", "ro" ] } ], "linux": { "namespaces": [ { "type": "pid" }, { "type": "network" }, { "type": "ipc" }, { "type": "uts" }, { "type": "mount" } ] } }
主要在于修改capabilities中的一些
CAP_SETUID CAP_SETGID CAP_FOWNER
权限以及mount中的信息 -
确保路径
/.../alpine-bundle
的文件夹都有执行权限,没有的话可以使用chmod +x file_dir_name
命令添加 -
确保
alpine-bundle/
下的所有文件都有必须的执行权限,这里我们直接chmod 775 -R alpine-bundle/
-
由于runc目前存在的问题fix permission denied,我们需要将
alpine-bundle
的owner改成root,执行chown root:root -R alpine-bundle/
,如下为rootfs下的文件信息eric@ubuntu:~/images_tmp$ lsl alpine-bundle/rootfs/ total 68 drwxrwxr-x 2 root root 4096 Oct 21 21:39 bin drwxrwxr-x 2 root root 4096 Oct 21 21:39 dev ... drwxrwxr-x 7 root root 4096 Oct 21 21:39 usr drwxrwxr-x 11 root root 4096 Oct 21 21:39 var
-
在当前文件夹下
alpine-bundle/
下执行sudo runc run hello
,其中hello
为容器的名字eric@ubuntu:~/images_tmp/alpine-bundle$ sudo runc run hello / # whoami root
-
执行
adduser
命令并login
/ # adduser jeff Changing password for jeff New password: Bad password: too short Retype password: passwd: password for jeff changed by root / # login jeff Password: Welcome to Alpine! The Alpine Wiki contains a large amount of how-to guides and general information about administrating Alpine systems. See <http://wiki.alpinelinux.org/>. You can setup the system with the command: setup-alpine You may change this message by editing /etc/motd. ubuntu:~$
能够正常添加用户并登陆了。
问题与解决
如果按照上述过程执行的话应该不会遇到问题,如下的问题是我在摸索过程中遇到的,感兴趣的可以参考。
-
root运行
runc run
出现chdir
错误- 原因是目标目录的owner与当前用户(root)不同,一个解决方案是chown,参考#2086
-
alpine容器内添加用户
adduser
出错 -permission denied
- 容器权限 - 容器需要
setuid, setgid, setfcap
等权限 - 目录可执行位 - 容器文件系统目录及其父目录需要有所有用户的可执行权限(755: rwxrwxr-x)
- 容器权限 - 容器需要
-
alpine容器
login/su
出错 -login: can't execute '/bin/ash': Permission denied
- 目录可读、可执行位(
chmod 755
),使用chmod 755 -R rootfs
命令将所有文件权限设为可读,参考Can’t change to home directory - 链接库的可执行位,使用
ldd
命令查看链接库,与1同理,参考unable-to-su-with-root-bin-bash-permission-denied的第二个回答
- 目录可读、可执行位(
总结
Linux的权限信息比较复杂,感兴趣的可以参考手册。本文主要以记录为主,欢迎评论。