了解docker入口脚本

脚本位于这里: https : //github.com/docker-library/ghost/blob/master/docker-entrypoint.sh

#!/bin/bash set -e if [[ "$*" == npm*start* ]]; then baseDir="$GHOST_SOURCE/content" for dir in "$baseDir"/*/ "$baseDir"/themes/*/; do targetDir="$GHOST_CONTENT/${dir#$baseDir/}" mkdir -p "$targetDir" if [ -z "$(ls -A "$targetDir")" ]; then tar -c --one-file-system -C "$dir" . | tar xC "$targetDir" fi done if [ ! -e "$GHOST_CONTENT/config.js" ]; then sed -r ' s/127\.0\.0\.1/0.0.0.0/g; s!path.join\(__dirname, (.)/content!path.join(process.env.GHOST_CONTENT, \1!g; ' "$GHOST_SOURCE/config.example.js" > "$GHOST_CONTENT/config.js" fi ln -sf "$GHOST_CONTENT/config.js" "$GHOST_SOURCE/config.js" chown -R user "$GHOST_CONTENT" set -- gosu user "$@" fi exec "$@" 

据我所知,它说,如果你使用npm start一些变化来将一些文件从$GHOST_SOURCE$GHOST_CONTENT ,那么对config.js文件做一些操作,链接configuration文件,设置内容文件的所有权,然后以用户user身份执行npm start 。 否则,它只是正常运行你的命令。

具体是什么是我难以理解,因为有很多事情从bash,我从来没有见过。 所以我有很多问题

 for dir in "$baseDir"/*/ "$baseDir"/themes/*/; do 

在上面,为什么要指定/*//themes/*/ ? 不应该/*/包含主题? 由于某种原因*不是通配符?

 targetDir="$GHOST_CONTENT/${dir#$baseDir/}" 

在上面,variables扩展中的#是什么?

 tar -c --one-file-system -C "$dir" . | tar xC "$targetDir" 

在上面,这不知何故节省时间? 为什么不使用rsync这样的东西? 我明白-C ,但为什么-c--one-file-system

 sed -r ' s/127\.0\.0\.1/0.0.0.0/g; s!path.join\(__dirname, (.)/content!path.join(process.env.GHOST_CONTENT, \1!g; ' "$GHOST_SOURCE/config.example.js" > "$GHOST_CONTENT/config.js" 

这个sed命令是做什么的? 我知道这是一个替代,但为什么"$GHOST_SOURCE/config.example.js" > "$GHOST_CONTENT/config.js"为结束?

 ln -sf "$GHOST_CONTENT/config.js" "$GHOST_SOURCE/config.js" 

在上面,这个符号链接的目的是什么? 如果两个文件都已经存在,为什么要将它们链接到对方呢?

 set -- gosu user "$@" 

在上面什么调用没有参数set吗?

我希望这不是太多。 我觉得提出一个单独的问题,因为每个问题都是相互关联的,

 for dir in "$baseDir"/*/ "$baseDir"/themes/*/; do 

在上面,为什么要指定/*//themes/*/ ? 不应该/*/包含主题? 由于某种原因*不是通配符?

主题/在第一个匹配,但主题/ * /不是,所以你需要第二个条目包括主题的内容。

 targetDir="$GHOST_CONTENT/${dir#$baseDir/}" 

在上面,variables扩展中的#是什么?

它从$ dir中删除$ baseDir前缀。 举个例子:

 bash$ dir=/home/bmitch/data/docker bash$ echo $dir /home/bmitch/data/docker bash$ echo ${dir#/home/bmitch} /data/docker 
 tar -c --one-file-system -C "$dir" . | tar xC "$targetDir" 

在上面,这不知何故节省时间? 为什么不使用rsync这样的东西? 我明白-C的意思,但为什么-c和–one-file-system?

rsync可能没有安装在每台机器上,默认情况下,tar是相当通用的。 -c是创buildvs提取文件,而–one-file-system避免了tar继续到外部挂载点(nfs,符号链接到root等)。

 sed -r ' s/127\.0\.0\.1/0.0.0.0/g; s!path.join\(__dirname, (.)/content!path.join(process.env.GHOST_CONTENT, \1!g; ' "$GHOST_SOURCE/config.example.js" > "$GHOST_CONTENT/config.js" 

这个sed命令是做什么的? 我知道这是一个替代,但为什么“$ GHOST_SOURCE / config.example.js”>“$ GHOST_CONTENT / config.js”为结束?

config.example.js是input(最后一个参数为sed),config.js是输出(在>之后)。 因此,它需要config.example.js,将IP地址从127.0.0.1更改为0.0.0.0,有效地监听所有接口/ IP,而不是在内部环回。 sed的后半部分将path.join参数从__dirname更改为process.env.GHOST_CONTENT。

 ln -sf "$GHOST_CONTENT/config.js" "$GHOST_SOURCE/config.js" 

在上面,这个符号链接的目的是什么? 如果两个文件都已经存在,为什么要将它们链接到对方呢?

$ GHOST_SOURCE / config.js被replace(-f),链接到$ GHOST_CONTENT / config.js。 符号链接提供了一个文件名引用另一个实际的文件,所以会有两个名字,但一个数据副本,这意味着你将只有一个configuration在这种情况下。

 set -- gosu user "$@" 

在上面什么调用没有参数设置吗?

这将$ 1,$ 2,… $ n的值更改为$ 1 = gosu,$ 2 = user,$ 3 =旧的$ 1,$ 4 =旧的$ 2 …,基本上将gosu和用户添加到将parameter passing给脚本。 – 确保set不会将$ @中的任何值解释为自己的标志。