了解docker入口点脚本

时间:2016-06-08 00:41:00

标签: bash sed 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文件执行某些操作,链接配置文件,设置内容文件的所有权,然后以用户npm start执行user。否则,它只是正常运行您的命令。

细节是我难以理解的,因为bash中有很多我以前从未见过的东西。所以我有很多问题。

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

在上文中,为什么他们同时指定/*//themes/*/?不应该/*/包含主题吗?由于某种原因,*不是通配符吗?

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

在上面,变量扩展中#的重点是什么?

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没有args的是什么?

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

1 个答案:

答案 0 :(得分:2)

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

在上文中,为什么他们同时指定/*//themes/*/?不该'吨   /*/包含主题?由于某种原因,*不是通配符吗?

themes /是第一场比赛,但是主题/ * /不是,所以你需要第二个条目来包含主题的内容。

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

在上面,变量扩展中#的重点是什么?

它从$ 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是创建,vs提取和--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是输入(sed的最后一个arg),config.js是输出(在>之后)。所以需要config.example.js,将ip地址从127.0.0.1更改为0.0.0.0,有效地监听所有接口/ ip,而不是仅仅在内环上。 sed的后半部分是将__dirname中的path.join参数更改为process.env.GHOST_CONTENT。

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

在上面,这个符号链接有什么意义?为什么要尝试链接它们   如果两个文件都已存在,那么它们会互相生效吗?

$ GHOST_SOURCE / config.js被替换为(-f)并带有$ GHOST_CONTENT / config.js的链接。符号链接提供对另一个实际文件的文件名引用,因此将有两个名称,但是数据的一个副本,这意味着在这种情况下您将只有一个配置。

set -- gosu user "$@"
     

在上面,没有args的调用set会怎么做?

这会将$ 1,$ 2,... $ n的值更改为$ 1 = gosu,$ 2 =用户,$ 3 =旧$ 1,$ 4 =旧$ 2 ...,实际上是将gosu和用户添加到传递给脚本的参数的开头。 - 确保set不会将$ @中的任何值解释为自身的标志。