在 docker 中以普通用户权限运行单节点 DolphinDB
在正式环境部署某个 docker 服务的时候,为了方便权限管理,服务部署者会以普通用户进行操作。在操作的过程中,我们通常需要把宿主机的某些文件挂载到容器内部,也需要把容器内部的文件映射到宿主机。在这个操作过程中,通常会遇到一些权限的问题,特别是将容器内部的文件映射到宿主机的时候,虽然我们是以普通用户权限运行的 docker,但是映射到宿主机的文件为什么就变成 root 权限了。创作本文就是为了解决上述问题。
1. 理解 docker 容器的 uid
docker 容器运行的时候,如果没有专门指定 user, 默认以 root 用户运行。
容器共享宿主机的 uid
Linux 内核负责管理 uid 和 gid,并通过内核级别的系统调用来决定是否通过请求的权限。
比如,当一个进程尝试去写文件,内核会检查创建这个进程的的 user 的 uid 和 gid,来决定这个进程是否有权限修改这个文件,这里没有使用 username,而是 uid。
当 docker 容器运行在宿主机上的时候,仍然只有一个内核。容器共享宿主机的内核,所以所有的 uid 和 gid 都受同一个内核来控制。
那为什么我容器里的用户名不一定和宿主内核一样呢?
比如,test 容器的用户叫做 test, 而本机没有 test 这个用户。这是因为 test 不是 Linux 内核的一部分。简单地说,username 是对 uid 的一个映射。然而,权限控制的依据是 uid,而不是 username。
2. 创建一个普通用户运行的 dolphindb 单节点 server
2.1 查询当前用户的 uid 和 gid
执行:
cat /etc/passwd | grep ${USER}
返回:
xhtang:x:1002:1002::/home/xhtang:/bin/bash
当前用户的 username 是 xhtang,uid 和 gid 都是1002。
容器共享宿主机的 core dump 配置
查询宿主机的 core dump 配置,执行:
cat /proc/sys/kernel/core_pattern
返回:
/hdd/hdd1/corefile/%e.core.%t
2.2 构建镜像
创建文件:
- 包含 DolphinDB server 的 server 目录
- 容器启动后执行的脚本 default_cmd
- 镜像构建的 Dockerfile
default_cmd
#!/bin/bash
#default_cmd
set -e
cd /home/xhtang
mkdir -p /home/xhtang/hdd/log
echo "The start-time is $(date)" >> /home/xhtang/hdd/log/run.log
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/xhtang/server
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/xhtang/server/plugins
nohup /home/xhtang/server/dolphindb -console 0 -home /home/xhtang/hdd/homeDir -logFile /home/xhtang/hdd/log/dolphindb.log >> /home/xhtang/hdd/log/startsingle.log 2>&1 &
echo "The complete-time is $(date)" >> /home/xhtang/hdd/log/run.log
sleep infinity
Dockerfile
#the user is root
#Operating System
FROM centos:7
#Use the East eight zone time zone
ENV TIME_ZONE Asia/Shanghai
RUN ln -snf /usr/share/zoneinfo/$TIME_ZONE /etc/localtime
#Create the same user group as host
RUN groupadd xhtang -g 1002
#Create the same user as host
RUN useradd -d /home/xhtang -u 1002 -g 1002 xhtang
#Create core-dump dir
RUN mkdir -p /hdd/hdd1
#ADD file and change permission
RUN chown -R 1002:1002 /hdd/hdd1
ADD server /home/xhtang/server
RUN chown -R 1002:1002 /home/xhtang/server
ADD default_cmd /home/xhtang/default_cmd
RUN chown -R 1002:1002 /home/xhtang/default_cmd
#Change user to xhtang
USER xhtang
#Default workdir
WORKDIR /home/xhtang
#Give executable permission
RUN chmod +x /home/xhtang/server/dolphindb
RUN chmod +x /home/xhtang/default_cmd
#ENTRYPOINT
ENTRYPOINT ["/home/xhtang/default_cmd"]
准备好上述三个文件后,在文件所在目录执行:
docker build -t singleddb ./
查看构建好的镜像 singleddb,执行:
docker images
返回:
REPOSITORY TAG IMAGE ID CREATED SIZE
singleddb latest c3d155b48217 6 seconds ago 411 MB
2.3 创建 docker-compose.yml
创建文件:
- config 目录
- docker-compose.yml
config 目录
- dolphindb.lic
DolphinDB server 的 license 文件。
- dolphindb.cfg
DolphinDB server 的 配置文件。
localSite=localhost:8800:local8800
mode=single
maxMemSize=32
maxConnections=512
workerNum=16
localExecutors=15
newValuePartitionPolicy=add
webWorkerNum=8
dataSync=1
chunkCacheEngineMemSize=8
logLevel=INFO
volumes=/home/xhtang/hdd/volumes
diskIOConcurrencyLevel=1
redoLogDir=/home/xhtang/ssd/redoLog
dfsMetaDir=/home/xhtang/ssd/dfsMeta
chunkMetaDir=/home/xhtang/ssd/chunkMeta
persistenceDir=/home/xhtang/ssd/persistenceDir
maxPubConnections=64
subExecutors=8
subPort=8801
subThrottle=1
persistenceWorkerNum=1
lanCluster=0
docker-compose.yml
version: '3'
services:
mix1:
image: singleddb:latest
container_name: singleDDB1
user: "1002"
ulimits:
memlock:
soft: -1
hard: -1
nofile:
soft: 65536
hard: 65536
volumes:
- ./config/dolphindb.lic:/home/xhtang/server/dolphindb.lic
- ./config/dolphindb.cfg:/home/xhtang/server/dolphindb.cfg
- ./ssd:/home/xhtang/ssd
- ./hdd:/home/xhtang/hdd
ports:
- "25000:8800"
- "25001:8801"
networks:
singleDDB:
ipv4_address: 172.20.0.6
networks:
singleDDB:
driver: bridge
ipam:
config:
- subnet: 172.20.0.0/16
2.4 运行 docker-compose
initialization.sh
#!/bin/bash
#start
set -e
rm -rf ssd hdd
mkdir ssd hdd
docker-compose -f docker-compose.yml down
echo "Start initialization!"
docker-compose -f docker-compose.yml up -d
echo "initialization complete!"
start.sh
#!/bin/bash
#start
set -e
docker-compose -f docker-compose.yml down
echo "Start the docker!"
docker-compose -f docker-compose.yml up -d
echo "complete!"
stop.sh
#!/bin/bash
#stop
set -e
echo "start to stop!"
docker-compose -f docker-compose.yml down
echo "stop complete!"
参考
附录
1. 查询网络
执行:
docker network ls
返回:
NETWORK ID NAME DRIVER SCOPE
5fa36038315d bridge bridge local
24c622b45e01 docker_dbnet bridge local
e1c3e15606a9 haddb_dbnet bridge local
2be738b4c1e7 host host local
291b571a6721 none null local
如果收到与以下所示类似的错误,则表明现有容器正在使用该网络,要删除网络,必须先删除容器。
Error response from daemon: network my-bridge-network id 6f5293268bb91ad2498b38b0bca970083af87237784017be24ea208d2233c5aa has active endpoints
2. 删除网络
执行:
docker network rm 24c622b45e01
删除所有未使用的网络,执行:
docker network prune -f