@@ -54,7 +54,7 @@ readarray -t DISKS_METADATA_PATHS < <(clickhouse extract-from-config --config-fi
5454CLICKHOUSE_USER=" ${CLICKHOUSE_USER:- default} "
5555CLICKHOUSE_PASSWORD_FILE=" ${CLICKHOUSE_PASSWORD_FILE:- } "
5656if [[ -n " ${CLICKHOUSE_PASSWORD_FILE} " && -f " ${CLICKHOUSE_PASSWORD_FILE} " ]]; then
57- CLICKHOUSE_PASSWORD=" $( cat " ${CLICKHOUSE_PASSWORD_FILE} " ) "
57+ CLICKHOUSE_PASSWORD=" $( cat " ${CLICKHOUSE_PASSWORD_FILE} " ) "
5858fi
5959CLICKHOUSE_PASSWORD=" ${CLICKHOUSE_PASSWORD:- } "
6060CLICKHOUSE_DB=" ${CLICKHOUSE_DB:- } "
@@ -88,29 +88,47 @@ function create_directory_and_do_chown() {
8888 fi
8989}
9090
91- create_directory_and_do_chown " $DATA_DIR "
92-
93- # Change working directory to $DATA_DIR in case there're paths relative to $DATA_DIR, also avoids running
94- # clickhouse-server at root directory.
95- cd " $DATA_DIR "
96-
97- for dir in " $ERROR_LOG_DIR " \
98- " $LOG_DIR " \
99- " $TMP_DIR " \
100- " $USER_PATH " \
101- " $FORMAT_SCHEMA_PATH " \
102- " ${DISKS_PATHS[@]} " \
103- " ${DISKS_METADATA_PATHS[@]} "
104- do
105- create_directory_and_do_chown " $dir "
106- done
107-
108- if [ " $CLICKHOUSE_SKIP_USER_SETUP " == " 1" ]; then
109- echo " $0 : explicitly skip changing user 'default'"
110- # if clickhouse user is defined - create it (user "default" already exists out of box)
111- elif [ -n " $CLICKHOUSE_USER " ] && [ " $CLICKHOUSE_USER " != " default" ] || [ -n " $CLICKHOUSE_PASSWORD " ] || [ " $CLICKHOUSE_ACCESS_MANAGEMENT " != " 0" ]; then
112- echo " $0 : create new user '$CLICKHOUSE_USER ' instead 'default'"
113- cat << EOT > /etc/clickhouse-server/users.d/default-user.xml
91+ function manage_clickhouse_directories() {
92+ for dir in " $ERROR_LOG_DIR " \
93+ " $LOG_DIR " \
94+ " $TMP_DIR " \
95+ " $USER_PATH " \
96+ " $FORMAT_SCHEMA_PATH " \
97+ " ${DISKS_PATHS[@]} " \
98+ " ${DISKS_METADATA_PATHS[@]} "
99+ do
100+ create_directory_and_do_chown " $dir "
101+ done
102+ }
103+
104+ function manage_clickhouse_user() {
105+ # Check if the `defaul` user is changed through any mounted file. It will mean that user took care of it already
106+ # First, extract the users_xml.path and check it's relative or absolute
107+ local USERS_XML USERS_CONFIG
108+ USERS_XML=$( clickhouse extract-from-config --config-file " $CLICKHOUSE_CONFIG " --key=' user_directories.users_xml.path' )
109+ case $USERS_XML in
110+ /* ) # absolute path
111+ cp " $USERS_XML " /tmp
112+ USERS_CONFIG=" /tmp/$( basename $USERS_XML ) "
113+ ;;
114+ * ) # relative path to the $CLICKHOUSE_CONFIG
115+ cp " $( dirname " $CLICKHOUSE_CONFIG " ) /${USERS_XML} " /tmp
116+ USERS_CONFIG=" /tmp/$( basename $USERS_XML ) "
117+ ;;
118+ esac
119+
120+ # Compare original `users.default` to the processed one
121+ local ORIGINAL_DEFAULT PROCESSED_DEFAULT CLICKHOUSE_DEFAULT_CHANGED
122+ ORIGINAL_DEFAULT=$( clickhouse extract-from-config --config-file " $USERS_CONFIG " --key=' users.default' | sha256sum)
123+ PROCESSED_DEFAULT=$( clickhouse extract-from-config --config-file " $CLICKHOUSE_CONFIG " --users --key=' users.default' --try | sha256sum)
124+ [ " $ORIGINAL_DEFAULT " == " $PROCESSED_DEFAULT " ] && CLICKHOUSE_DEFAULT_CHANGED=0 || CLICKHOUSE_DEFAULT_CHANGED=1
125+
126+ if [ " $CLICKHOUSE_SKIP_USER_SETUP " == " 1" ]; then
127+ echo " $0 : explicitly skip changing user 'default'"
128+ elif [ -n " $CLICKHOUSE_USER " ] && [ " $CLICKHOUSE_USER " != " default" ] || [ -n " $CLICKHOUSE_PASSWORD " ] || [ " $CLICKHOUSE_ACCESS_MANAGEMENT " != " 0" ]; then
129+ # if clickhouse user is defined - create it (user "default" already exists out of box)
130+ echo " $0 : create new user '$CLICKHOUSE_USER ' instead 'default'"
131+ cat << EOT > /etc/clickhouse-server/users.d/default-user.xml
114132<clickhouse>
115133 <!-- Docs: <https://clickhouse.com/docs/en/operations/settings/settings_users/> -->
116134 <users>
@@ -130,9 +148,12 @@ elif [ -n "$CLICKHOUSE_USER" ] && [ "$CLICKHOUSE_USER" != "default" ] || [ -n "$
130148 </ users>
131149</ clickhouse>
132150EOT
133- else
134- echo " $0 : neither CLICKHOUSE_USER nor CLICKHOUSE_PASSWORD is set, disabling network access for user '$CLICKHOUSE_USER '"
135- cat <<EOT > / etc/ clickhouse-server/ users.d/ default-user.xml
151+ elif [ "$CLICKHOUSE_DEFAULT_CHANGED" == "1" ]; then
152+ # Leave users as is, do nothing
153+ :
154+ else
155+ echo " $0 : neither CLICKHOUSE_USER nor CLICKHOUSE_PASSWORD is set, disabling network access for user '$CLICKHOUSE_USER '"
156+ cat <<EOT > / etc/ clickhouse-server/ users.d/ default-user.xml
136157<clickhouse>
137158 <! -- Docs: <https:// clickhouse.com/ docs/ en/ operations/ settings/ settings_users/ > -->
138159 <users>
@@ -146,85 +167,88 @@ else
146167 </ users>
147168</ clickhouse>
148169EOT
149- fi
170+ fi
171+ }
150172
151173CLICKHOUSE_ALWAYS_RUN_INITDB_SCRIPTS="${CLICKHOUSE_ALWAYS_RUN_INITDB_SCRIPTS:- } "
152174
153- # checking $DATA_DIR for initialization
154- if [ -d "${DATA_DIR%/}/data" ]; then
155- DATABASE_ALREADY_EXISTS=' true'
156- fi
157-
158- # run initialization if flag CLICKHOUSE_ALWAYS_RUN_INITDB_SCRIPTS is not empty or data directory is empty
159- if [[ -n "${CLICKHOUSE_ALWAYS_RUN_INITDB_SCRIPTS}" || -z "${DATABASE_ALREADY_EXISTS}" ]]; then
160- RUN_INITDB_SCRIPTS=' true'
161- fi
162-
163- if [ -n "${RUN_INITDB_SCRIPTS}" ]; then
164- if [ -n "$(ls /docker-entrypoint-initdb.d/)" ] || [ -n "$CLICKHOUSE_DB" ]; then
165- # port is needed to check if clickhouse-server is ready for connections
166- HTTP_PORT=" $( clickhouse extract-from-config --config-file " $CLICKHOUSE_CONFIG " --key=http_port --try) "
167- HTTPS_PORT=" $( clickhouse extract-from-config --config-file " $CLICKHOUSE_CONFIG " --key=https_port --try) "
175+ function init_clickhouse_db() {
176+ # checking $DATA_DIR for initialization
177+ if [ -d "${DATA_DIR%/ } /data" ]; then
178+ DATABASE_ALREADY_EXISTS='true'
179+ fi
168180
169- if [ -n "$HTTP_PORT" ]; then
170- URL=" http://127.0.0.1:$HTTP_PORT /ping"
171- else
172- URL=" https://127.0.0.1:$HTTPS_PORT /ping"
173- fi
181+ # run initialization if flag CLICKHOUSE_ALWAYS_RUN_INITDB_SCRIPTS is not empty or data directory is empty
182+ if [[ -n "${CLICKHOUSE_ALWAYS_RUN_INITDB_SCRIPTS} " || -z "${DATABASE_ALREADY_EXISTS} " ]]; then
183+ RUN_INITDB_SCRIPTS='true'
184+ fi
174185
175- # Listen only on localhost until the initialization is done
176- clickhouse su " ${USER} :${GROUP} " clickhouse-server --config-file=" $CLICKHOUSE_CONFIG " -- --listen_host=127.0.0.1 &
177- pid=" $! "
186+ if [ -n "${RUN_INITDB_SCRIPTS} " ]; then
187+ if [ -n "$( ls /docker-entrypoint-initdb.d/) " ] || [ -n "$CLICKHOUSE_DB " ]; then
188+ # port is needed to check if clickhouse-server is ready for connections
189+ HTTP_PORT="$( clickhouse extract-from-config --config-file " $CLICKHOUSE_CONFIG " --key=http_port --try) "
190+ HTTPS_PORT="$( clickhouse extract-from-config --config-file " $CLICKHOUSE_CONFIG " --key=https_port --try) "
178191
179- # check if clickhouse is ready to accept connections
180- # will try to send ping clickhouse via http_port (max 1000 retries by default, with 1 sec timeout and 1 sec delay between retries)
181- tries=${CLICKHOUSE_INIT_TIMEOUT:- 1000}
182- while ! wget --spider --no-check-certificate -T 1 -q " $URL " 2>/ dev/ null; do
183- if [ "$tries" -le "0" ]; then
184- echo >&2 ' ClickHouse init process timeout.'
185- exit 1
192+ if [ -n "$HTTP_PORT " ]; then
193+ URL="http://127.0.0.1:$HTTP_PORT /ping"
194+ else
195+ URL="https://127.0.0.1:$HTTPS_PORT /ping"
186196 fi
187- tries=$(( tries-1 ))
188- sleep 1
189- done
190197
191- clickhouseclient=( clickhouse-client --multiquery --host " 127.0.0.1" -u " $CLICKHOUSE_USER " --password " $CLICKHOUSE_PASSWORD " )
198+ # Listen only on localhost until the initialization is done
199+ clickhouse su "${USER} :${GROUP} " clickhouse-server --config-file="$CLICKHOUSE_CONFIG " -- --listen_host=127.0.0.1 &
200+ pid="$! "
192201
193- echo
202+ # check if clickhouse is ready to accept connections
203+ # will try to send ping clickhouse via http_port (max 1000 retries by default, with 1 sec timeout and 1 sec delay between retries)
204+ tries=${CLICKHOUSE_INIT_TIMEOUT:- 1000}
205+ while ! wget --spider --no-check-certificate -T 1 -q "$URL " 2>/dev/null; do
206+ if [ "$tries " -le "0" ]; then
207+ echo >&2 'ClickHouse init process timeout.'
208+ exit 1
209+ fi
210+ tries=$(( tries- 1 ))
211+ sleep 1
212+ done
194213
195- # create default database, if defined
196- if [ -n "$CLICKHOUSE_DB" ]; then
197- echo " $0 : create database '$CLICKHOUSE_DB '"
198- " ${clickhouseclient[@]} " -q " CREATE DATABASE IF NOT EXISTS $CLICKHOUSE_DB " ;
199- fi
214+ clickhouseclient=( clickhouse-client --multiquery --host "127.0.0.1" -u "$CLICKHOUSE_USER " --password "$CLICKHOUSE_PASSWORD " )
200215
201- for f in / docker-entrypoint-initdb.d/* ; do
202- case " $f " in
203- * .sh)
204- if [ -x "$f" ]; then
205- echo " $0 : running $f "
206- " $f "
207- else
208- echo " $0 : sourcing $f "
209- # shellcheck source=/ dev/ null
210- . " $f "
211- fi
212- ;;
213- * .sql) echo " $0 : running $f " ; " ${clickhouseclient[@]} " < " $f " ; echo ;;
214- * .sql.gz) echo " $0 : running $f " ; gunzip -c " $f " | " ${clickhouseclient[@]} " ; echo ;;
215- * ) echo " $0 : ignoring $f " ;;
216- esac
217216 echo
218- done
219217
220- if ! kill -s TERM " $pid " || ! wait " $pid " ; then
221- echo >&2 ' Finishing of ClickHouse init process failed.'
222- exit 1
218+ # create default database, if defined
219+ if [ -n "$CLICKHOUSE_DB " ]; then
220+ echo "$0 : create database '$CLICKHOUSE_DB '"
221+ "${clickhouseclient[@]} " -q "CREATE DATABASE IF NOT EXISTS $CLICKHOUSE_DB ";
222+ fi
223+
224+ for f in /docker-entrypoint-initdb.d/*; do
225+ case "$f " in
226+ *.sh)
227+ if [ -x "$f " ]; then
228+ echo "$0 : running $f "
229+ "$f "
230+ else
231+ echo "$0 : sourcing $f "
232+ # shellcheck source=/dev/null
233+ . "$f "
234+ fi
235+ ;;
236+ *.sql) echo "$0 : running $f "; "${clickhouseclient[@]} " < "$f " ; echo ;;
237+ *.sql.gz) echo "$0 : running $f "; gunzip -c "$f " | "${clickhouseclient[@]} "; echo ;;
238+ *) echo "$0 : ignoring $f " ;;
239+ esac
240+ echo
241+ done
242+
243+ if ! kill -s TERM "$pid " || ! wait "$pid "; then
244+ echo >&2 'Finishing of ClickHouse init process failed.'
245+ exit 1
246+ fi
223247 fi
248+ else
249+ echo "ClickHouse Database directory appears to contain a database; Skipping initialization"
224250 fi
225- else
226- echo " ClickHouse Database directory appears to contain a database; Skipping initialization"
227- fi
251+ }
228252
229253# if no args passed to ` docker run` or first argument start with ` --` , then the user is passing clickhouse-server arguments
230254if [[ $# -lt 1 ]] || [[ "$1 " == "--"* ]]; then
@@ -233,9 +257,24 @@ if [[ $# -lt 1 ]] || [[ "$1" == "--"* ]]; then
233257 CLICKHOUSE_WATCHDOG_ENABLE=${CLICKHOUSE_WATCHDOG_ENABLE:- 0}
234258 export CLICKHOUSE_WATCHDOG_ENABLE
235259
260+ create_directory_and_do_chown "$DATA_DIR "
261+
262+ # Change working directory to $DATA_DIR in case there're paths relative to $DATA_DIR , also avoids running
263+ # clickhouse-server at root directory.
264+ cd "$DATA_DIR "
265+
266+ # Using functions here to avoid unnecessary work in case of launching other binaries,
267+ # inspired by postgres, mariadb etc. entrypoints
268+ # It is necessary to pass the docker library consistency test
269+ manage_clickhouse_directories
270+ manage_clickhouse_user
271+ init_clickhouse_db
272+
236273 # This replaces the shell script with the server:
237274 exec clickhouse su "${USER} :${GROUP} " clickhouse-server --config-file="$CLICKHOUSE_CONFIG " "$@ "
238275fi
239276
240277# Otherwise, we assume the user want to run his own process, for example a ` bash` shell to explore this image
241278exec "$@ "
279+
280+ # vi: ts=4: sw=4: sts=4: expandtab
0 commit comments