虽然 linux 有 user namespace 隔离技术,但是 docker 不支持类似 podman 那样的给每个容器设置范围性的 uidmap 映射(当然 k8s 现在也不支持),并且容器默认配置下的权限虽然去掉了一些。但是容器内还是能对挂载进去的进行修改的,比如帖子 rm -rf * 前一定一定要看清当前目录 老哥的操作:
1 2 3 4 5 6 7 8
docker run --rm -v /mnt/sda1:/mnt/sda1 -it alpine cp /mnt/sda1/somefile.tar.gz . tar xzvf somefile.tar.gz cd somefile-v1.0 ls # 看了看内容觉得不是自己想要的,回上一级目录准备删掉: cd .. rm -rf *
#!/bin/sh # 脚本某行报错就退出 set -e # 脚本的第一个参数为 -开头的字符串,或者是 .conf 结尾的字符串 if [ "${1#-}" != "$1" ] || [ "${1%.conf}" != "$1" ]; then # 重新设置 $@ 为 redis-server "$@" set -- redis-server "$@" fi
# allow the container to be started with `--user` # 第一个参数为 redis-server 并且执行的用户为 root if [ "$1" = 'redis-server' -a "$(id -u)" = '0' ]; then # 更改当前目录下的 owner 为 redis find . \! -user redis -execchown redis '{}' + # 使用 gosu 切换到 redis 执行本脚本,并带上此刻的 $@参数 exec gosu redis "$0""$@" fi
# set an appropriate umask (if one isn't set already) # - https://github.com/docker-library/redis/issues/305 # - https://github.com/redis/redis/blob/bb875603fb7ff3f9d19aad906bd45d7db98d9a39/utils/systemd-redis_server.service#L37 um="$(umask)" if [ "$um" = '0022' ]; then umask 0077 fi
funcmain() { // Find SMBIOS data in operating system-specific location. rc, ep, err := smbios.Stream() if err != nil { log.Fatalf("failed to open stream: %v", err) } // Be sure to close the stream! defer rc.Close()
// Decode SMBIOS structures from the stream. d := smbios.NewDecoder(rc) ss, err := d.Decode() if err != nil { log.Fatalf("failed to decode structures: %v", err) }
major, minor, _ := ep.Version()
for _, s := range ss { if s.Header.Type == 1 { d := s.Formatted // https://github.com/mirror/dmidecode/blob/dmidecode-3-5/dmidecode.c#L485 if major > 0x02 || (major == 0x02 && minor >= 0x06) { fmt.Printf("UUID: %02X%02X%02X%02X-%02X%02X-%02X%02X-%02X%02X-%02X%02X%02X%02X%02X%02X\n", d[7], d[6], d[5], d[4], d[9], d[8], d[11], d[10], d[12], d[13], d[14], d[15], d[16], d[17], d[18], d[19], ) } else { fmt.Printf("UUID: %02X%02X%02X%02X-%02X%02X-%02X%02X-%02X%02X-%02X%02X%02X%02X%02X%02X\n", d[4], d[5], d[6], d[7], d[8], d[9], d[10], d[11], d[12], d[13], d[14], d[15], d[16], d[17], d[18], d[19], ) } } } }
$ cat /proc//sys/net/ipv4/ip_unprivileged_port_start 1024 $ uname -a Linux guan 5.4.0-216-generic #236-Ubuntu SMP Fri Apr 11 19:53:21 UTC 2025 x86_64 x86_64 x86_64 GNU/Linux $ cat /proc/sys/net/ipv4/ip_unprivileged_port_start cat: /proc/sys/net/ipv4/ip_unprivileged_port_start: No such file or directory $ uname -a Linux reg.xxx.lan 3.10.0-1127.el7.x86_64 #1 SMP Tue Mar 31 23:36:51 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux
另外在 docker 源码里看到由如下逻辑:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
// https://github.com/moby/moby/blob/acc9563f4894f5280d39d0b138b5dc5ce5e34724/daemon/oci_linux.go#L753-L767 // Add default sysctls that are generally safe and useful; currently we // grant the capabilities to allow these anyway. You can override if // you want to restore the original behaviour. // We do not set network sysctls if network namespace is host, or if we are // joining an existing namespace, only if we create a new net namespace. if c.HostConfig.NetworkMode.IsPrivate() { // We cannot set up ping socket support in a user namespace userNS := daemonCfg.RemappedRoot != "" && c.HostConfig.UsernsMode.IsPrivate() if !userNS && !userns.RunningInUserNS() && sysctlExists("net.ipv4.ping_group_range") { // allow unprivileged ICMP echo sockets without CAP_NET_RAW s.Linux.Sysctl["net.ipv4.ping_group_range"] = "0 2147483647" } // allow opening any port less than 1024 without CAP_NET_BIND_SERVICE if sysctlExists("net.ipv4.ip_unprivileged_port_start") { s.Linux.Sysctl["net.ipv4.ip_unprivileged_port_start"] = "0" } }
function main(){ local remote_type_list=("oss" "s3" ...) local run_type item found=0
run_type=$(echo $XXXXX_RUN_TYPE| sed -r 's#(server|gateway)\s*##') for item in "${remote_type_list[@]}"; do if [ "$item" = "$run_type" ]; then found=1 break fi done if [ "$found" = 1 ];then exec gosu nobody ... else exec ... fi } main $@
后端网络存储则非root,本地文件则 root,如果本地文件也非 root,则必须在启动脚本内先 chown,但是很多客户升级上来的,升级启动执行 chown 会很久,甚至某些 nas 不允许 chown 之类的。