在入口点脚本中执行后如何清理临时文件?
How to clean up temporary files after exec-ing inside entrypoint script?
我正在尝试编写自己的 mariadb docker 图像。我想在容器启动后(exec mysqld
之后)执行一些 sql 语句。但是我发现 mysqld --init-file
选项对我的情况很有用。所以我的入口点脚本如下所示。
Dockerfile
FROM alpine:edge
RUN set -ex \
&& apk add mariadb mariadb-client \
&& mkdir -p /run/mysqld \
&& chown -R mysql:mysql /run/mysqld \
&& ln -snf /usr/lib/mariadb /usr/lib/mysql \
&& mysql_install_db --user=mysql --skip-name-resolve --auth-root-authentication-method=socket --auth-root-socket-user=root --force --rpm --skip-test-db
COPY entrypoint.sh /
ENTRYPOINT ["/entrypoint.sh"]
EXPOSE 3306
CMD ["mysqld"]
entrypoint.sh
#!/bin/sh
set -ex
{
echo "CREATE USER IF NOT EXISTS '${MYSQL_USER}'@'%' IDENTIFIED BY '${MYSQL_PASSWORD}';"
echo "CREATE DATABASE IF NOT EXISTS ${MYSQL_DATABASE};"
echo "GRANT ALL ON ${MYSQL_DATABASE}.* TO '${MYSQL_USER}'@'%';"
} > /tmp/mysqld-init.sql
exec $@ --init-file="/tmp/mysqld-init.sql"
如您所见,临时初始化文件包含一些敏感信息。我想在执行 exec $@ --init-file="/tmp/mysqld-init.sql"
.
后清理它
现在我想到了两个想法。一种是为临时 sql 命令创建命名管道 (FIFO) 文件或使用 trap 命令。
想法一[=41=]
但这里的问题是不必要的子后台进程在容器上保留 运行,因为我使用了进程控制运算符 &
。但是我是徒劳的,我怎么退出那个过程。
if [ ! -p "/tmp/mysqld.init" ]; then
mkfifo /tmp/mysqld.init
fi
{
echo "CREATE USER IF NOT EXISTS '${MYSQL_USER}'@'%' IDENTIFIED BY '${MYSQL_PASSWORD}';"
echo "CREATE DATABASE IF NOT EXISTS ${MYSQL_DATABASE};"
echo "GRANT ALL ON ${MYSQL_DATABASE}.* TO '${MYSQL_USER}'@'%';"
} > /tmp/mysqld.init &
exec $@ --init-file="/tmp/mysqld.init"
想法2
执行exec
命令时,使用trap命令清理临时文件。但是我不知道如何捕捉exec信号。
trap cleanup "the exec signal"
cleanup()
{
echo "Caught Signal ... cleaning up."
rm -rf /tmp/mysqld-init.sql
echo "Done cleanup ... quitting."
exit 1
}
set -ex
{
echo "CREATE USER IF NOT EXISTS '${MYSQL_USER}'@'%' IDENTIFIED BY '${MYSQL_PASSWORD}';"
echo "CREATE DATABASE IF NOT EXISTS ${MYSQL_DATABASE};"
echo "GRANT ALL ON ${MYSQL_DATABASE}.* TO '${MYSQL_USER}'@'%';"
} > /tmp/mysqld-init.sql
exec $@ --init-file="/tmp/mysqld.init"
我认为 trap
是对此的最佳解决方案
function interrupt(){
local dir=
[ -e ${dir} ] && rm -rf ${dir}
exit 128
}
TMP_DIR=$(mktemp -d /tmp/entrypoint.XXXX)
trap "interrupt ${TMP_DIR}" SIGINT SIGTERM
trap "rm -rf ${TMP_DIR}" EXIT
set -ex
{
echo "CREATE USER IF NOT EXISTS '${MYSQL_USER}'@'%' IDENTIFIED BY '${MYSQL_PASSWORD}';"
echo "CREATE DATABASE IF NOT EXISTS ${MYSQL_DATABASE};"
echo "GRANT ALL ON ${MYSQL_DATABASE}.* TO '${MYSQL_USER}'@'%';"
} > ${TMP_DIR}/mysqld-init.sql
exec $@ --init-file="${TMP_DIR}/mysqld-init.sql"
使用tini解决这个信号和僵尸进程问题。
FROM alpine:edge
RUN set -ex \
&& apk add --no-cache mariadb mariadb-client tini \
&& mkdir -p /run/mysqld \
&& chown -R mysql:mysql /run/mysqld \
&& ln -snf /usr/lib/mariadb /usr/lib/mysql \
&& mysql_install_db --user=mysql --skip-name-resolve --auth-root-authentication-method=socket --auth-root-socket-user=root --force --rpm --skip-test-db
COPY entrypoint.sh /
ENTRYPOINT ["/entrypoint.sh"]
EXPOSE 3306
CMD ["mysqld"]
entrypoint.sh
if [ ! -p "/tmp/mysqld.init" ]; then
mkfifo /tmp/mysqld.init
fi
{
echo "CREATE USER IF NOT EXISTS '${MYSQL_USER}'@'%' IDENTIFIED BY '${MYSQL_PASSWORD}';"
echo "CREATE DATABASE IF NOT EXISTS ${MYSQL_DATABASE};"
echo "GRANT ALL ON ${MYSQL_DATABASE}.* TO '${MYSQL_USER}'@'%';"
} > /tmp/mysqld.init &
exec tini -g -- "$@" --init-file="/tmp/mysqld.init"
我正在尝试编写自己的 mariadb docker 图像。我想在容器启动后(exec mysqld
之后)执行一些 sql 语句。但是我发现 mysqld --init-file
选项对我的情况很有用。所以我的入口点脚本如下所示。
Dockerfile
FROM alpine:edge
RUN set -ex \
&& apk add mariadb mariadb-client \
&& mkdir -p /run/mysqld \
&& chown -R mysql:mysql /run/mysqld \
&& ln -snf /usr/lib/mariadb /usr/lib/mysql \
&& mysql_install_db --user=mysql --skip-name-resolve --auth-root-authentication-method=socket --auth-root-socket-user=root --force --rpm --skip-test-db
COPY entrypoint.sh /
ENTRYPOINT ["/entrypoint.sh"]
EXPOSE 3306
CMD ["mysqld"]
entrypoint.sh
#!/bin/sh
set -ex
{
echo "CREATE USER IF NOT EXISTS '${MYSQL_USER}'@'%' IDENTIFIED BY '${MYSQL_PASSWORD}';"
echo "CREATE DATABASE IF NOT EXISTS ${MYSQL_DATABASE};"
echo "GRANT ALL ON ${MYSQL_DATABASE}.* TO '${MYSQL_USER}'@'%';"
} > /tmp/mysqld-init.sql
exec $@ --init-file="/tmp/mysqld-init.sql"
如您所见,临时初始化文件包含一些敏感信息。我想在执行 exec $@ --init-file="/tmp/mysqld-init.sql"
.
现在我想到了两个想法。一种是为临时 sql 命令创建命名管道 (FIFO) 文件或使用 trap 命令。
想法一[=41=]
但这里的问题是不必要的子后台进程在容器上保留 运行,因为我使用了进程控制运算符 &
。但是我是徒劳的,我怎么退出那个过程。
if [ ! -p "/tmp/mysqld.init" ]; then
mkfifo /tmp/mysqld.init
fi
{
echo "CREATE USER IF NOT EXISTS '${MYSQL_USER}'@'%' IDENTIFIED BY '${MYSQL_PASSWORD}';"
echo "CREATE DATABASE IF NOT EXISTS ${MYSQL_DATABASE};"
echo "GRANT ALL ON ${MYSQL_DATABASE}.* TO '${MYSQL_USER}'@'%';"
} > /tmp/mysqld.init &
exec $@ --init-file="/tmp/mysqld.init"
想法2
执行exec
命令时,使用trap命令清理临时文件。但是我不知道如何捕捉exec信号。
trap cleanup "the exec signal"
cleanup()
{
echo "Caught Signal ... cleaning up."
rm -rf /tmp/mysqld-init.sql
echo "Done cleanup ... quitting."
exit 1
}
set -ex
{
echo "CREATE USER IF NOT EXISTS '${MYSQL_USER}'@'%' IDENTIFIED BY '${MYSQL_PASSWORD}';"
echo "CREATE DATABASE IF NOT EXISTS ${MYSQL_DATABASE};"
echo "GRANT ALL ON ${MYSQL_DATABASE}.* TO '${MYSQL_USER}'@'%';"
} > /tmp/mysqld-init.sql
exec $@ --init-file="/tmp/mysqld.init"
我认为 trap
是对此的最佳解决方案
function interrupt(){
local dir=
[ -e ${dir} ] && rm -rf ${dir}
exit 128
}
TMP_DIR=$(mktemp -d /tmp/entrypoint.XXXX)
trap "interrupt ${TMP_DIR}" SIGINT SIGTERM
trap "rm -rf ${TMP_DIR}" EXIT
set -ex
{
echo "CREATE USER IF NOT EXISTS '${MYSQL_USER}'@'%' IDENTIFIED BY '${MYSQL_PASSWORD}';"
echo "CREATE DATABASE IF NOT EXISTS ${MYSQL_DATABASE};"
echo "GRANT ALL ON ${MYSQL_DATABASE}.* TO '${MYSQL_USER}'@'%';"
} > ${TMP_DIR}/mysqld-init.sql
exec $@ --init-file="${TMP_DIR}/mysqld-init.sql"
使用tini解决这个信号和僵尸进程问题。
FROM alpine:edge
RUN set -ex \
&& apk add --no-cache mariadb mariadb-client tini \
&& mkdir -p /run/mysqld \
&& chown -R mysql:mysql /run/mysqld \
&& ln -snf /usr/lib/mariadb /usr/lib/mysql \
&& mysql_install_db --user=mysql --skip-name-resolve --auth-root-authentication-method=socket --auth-root-socket-user=root --force --rpm --skip-test-db
COPY entrypoint.sh /
ENTRYPOINT ["/entrypoint.sh"]
EXPOSE 3306
CMD ["mysqld"]
entrypoint.sh
if [ ! -p "/tmp/mysqld.init" ]; then
mkfifo /tmp/mysqld.init
fi
{
echo "CREATE USER IF NOT EXISTS '${MYSQL_USER}'@'%' IDENTIFIED BY '${MYSQL_PASSWORD}';"
echo "CREATE DATABASE IF NOT EXISTS ${MYSQL_DATABASE};"
echo "GRANT ALL ON ${MYSQL_DATABASE}.* TO '${MYSQL_USER}'@'%';"
} > /tmp/mysqld.init &
exec tini -g -- "$@" --init-file="/tmp/mysqld.init"