Skip to content

Commit bff9dbd

Browse files
committed
fix permissions issues - always using kool user/mapped UID
1 parent 9d9d6b5 commit bff9dbd

10 files changed

Lines changed: 453 additions & 1425 deletions

File tree

7.4-nginx-prod/Dockerfile

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@ RUN echo "Building Deps" \
1515
COPY --from=wordpress-cli /usr/local/bin/wp /usr/local/bin/wp
1616
COPY --from=wordpress --chown=kool:kool /usr/src/wordpress /kool/wordpress
1717
COPY --from=wordpress --chown=kool:kool /var/www/html/wp-content /app/wp-content
18-
COPY entrypoint /kool/entrypoint
18+
COPY entrypoint /kool/wordpress-entrypoint
1919

20-
RUN chmod -R 777 wp-content && chmod +x /kool/entrypoint
20+
RUN chmod -R 777 wp-content && chmod +x /kool/wordpress-entrypoint
21+
22+
ENTRYPOINT [ "/kool/wordpress-entrypoint" ]
23+
CMD [ "supervisord", "-c", "/kool/supervisor.conf" ]

7.4-nginx-prod/entrypoint

Lines changed: 86 additions & 283 deletions
Original file line numberDiff line numberDiff line change
@@ -1,290 +1,93 @@
11
#!/bin/bash
2-
set -euo pipefail
2+
set -eo pipefail
33

4-
dockerize -template /kool/kool.tmpl:/usr/local/etc/php/conf.d/kool.ini -template /kool/zz-docker.tmpl:/usr/local/etc/php-fpm.d/zz-docker.conf -template /kool/default.tmpl:/etc/nginx/conf.d/default.conf
4+
# Nginx server config
5+
dockerize -template /kool/default.tmpl:/etc/nginx/conf.d/default.conf
56

6-
# usage: file_env VAR [DEFAULT]
7-
# ie: file_env 'XYZ_DB_PASSWORD' 'example'
8-
# (will allow for "$XYZ_DB_PASSWORD_FILE" to fill in the value of
9-
# "$XYZ_DB_PASSWORD" from a file, especially for Docker's secrets feature)
10-
file_env() {
11-
local var="$1"
12-
local fileVar="${var}_FILE"
13-
local def="${2:-}"
14-
if [ "${!var:-}" ] && [ "${!fileVar:-}" ]; then
15-
echo >&2 "error: both $var and $fileVar are set (but are exclusive)"
16-
exit 1
17-
fi
18-
local val="$def"
19-
if [ "${!var:-}" ]; then
20-
val="${!var}"
21-
elif [ "${!fileVar:-}" ]; then
22-
val="$(< "${!fileVar}")"
23-
fi
24-
export "$var"="$val"
25-
unset "$fileVar"
26-
}
7+
# Run as current user
8+
CURRENT_USER=${ASUSER:-${UID:-0}}
279

28-
if [ "$1" == php-fpm ] || [ "$1" == supervisord ]; then
29-
if [ "$(id -u)" = '0' ]; then
30-
user='kool'
31-
group='kool'
32-
else
33-
user="$(id -u)"
34-
group="$(id -g)"
35-
fi
36-
37-
if [ ! -e index.php ] && [ ! -e wp-includes/version.php ]; then
38-
# if the directory exists and WordPress doesn't appear to be installed AND the permissions of it are root:root, let's chown it (likely a Docker-created directory)
39-
if [ "$(id -u)" = '0' ] && [ "$(stat -c '%u:%g' .)" = '0:0' ]; then
40-
chown "$user:$group" .
41-
fi
42-
43-
echo >&2 "WordPress not found in $PWD - copying now..."
44-
if [ -n "$(find -mindepth 1 -maxdepth 1 -not -name wp-content)" ]; then
45-
echo >&2 "WARNING: $PWD is not empty! (copying anyhow)"
46-
fi
47-
sourceTarArgs=(
48-
--create
49-
--file -
50-
--directory /kool/wordpress
51-
--owner "$user" --group "$group"
52-
)
53-
targetTarArgs=(
54-
--extract
55-
--file -
56-
)
57-
if [ "$user" != '0' ]; then
58-
# avoid "tar: .: Cannot utime: Operation not permitted" and "tar: .: Cannot change mode to rwxr-xr-x: Operation not permitted"
59-
targetTarArgs+=( --no-overwrite-dir )
60-
fi
61-
# loop over "pluggable" content in the source, and if it already exists in the destination, skip it
62-
# https://github.com/docker-library/wordpress/issues/506 ("wp-content" persisted, "akismet" updated, WordPress container restarted/recreated, "akismet" downgraded)
63-
for contentDir in /kool/wordpress/wp-content/*/*/; do
64-
contentDir="${contentDir%/}"
65-
[ -d "$contentDir" ] || continue
66-
contentPath="${contentDir#/kool/wordpress/}" # "wp-content/plugins/akismet", etc.
67-
if [ -d "$PWD/$contentPath" ]; then
68-
echo >&2 "WARNING: '$PWD/$contentPath' exists! (not copying the WordPress version)"
69-
sourceTarArgs+=( --exclude "./$contentPath" )
70-
fi
71-
done
72-
tar "${sourceTarArgs[@]}" . | tar "${targetTarArgs[@]}"
73-
echo >&2 "Complete! WordPress has been successfully copied to $PWD"
74-
if [ ! -e .htaccess ]; then
75-
# NOTE: The "Indexes" option is disabled in the php:apache base image
76-
cat > .htaccess <<-'EOF'
77-
# BEGIN WordPress
78-
<IfModule mod_rewrite.c>
79-
RewriteEngine On
80-
RewriteBase /
81-
RewriteRule ^index\.php$ - [L]
82-
RewriteCond %{REQUEST_FILENAME} !-f
83-
RewriteCond %{REQUEST_FILENAME} !-d
84-
RewriteRule . /index.php [L]
85-
</IfModule>
86-
# END WordPress
87-
EOF
88-
chown "$user:$group" .htaccess
89-
fi
90-
fi
91-
92-
# allow any of these "Authentication Unique Keys and Salts." to be specified via
93-
# environment variables with a "WORDPRESS_" prefix (ie, "WORDPRESS_AUTH_KEY")
94-
uniqueEnvs=(
95-
AUTH_KEY
96-
SECURE_AUTH_KEY
97-
LOGGED_IN_KEY
98-
NONCE_KEY
99-
AUTH_SALT
100-
SECURE_AUTH_SALT
101-
LOGGED_IN_SALT
102-
NONCE_SALT
103-
)
104-
envs=(
105-
WORDPRESS_DB_HOST
106-
WORDPRESS_DB_USER
107-
WORDPRESS_DB_PASSWORD
108-
WORDPRESS_DB_NAME
109-
WORDPRESS_DB_CHARSET
110-
WORDPRESS_DB_COLLATE
111-
"${uniqueEnvs[@]/#/WORDPRESS_}"
112-
WORDPRESS_TABLE_PREFIX
113-
WORDPRESS_DEBUG
114-
WORDPRESS_CONFIG_EXTRA
115-
)
116-
haveConfig=
117-
for e in "${envs[@]}"; do
118-
file_env "$e"
119-
if [ -z "$haveConfig" ] && [ -n "${!e}" ]; then
120-
haveConfig=1
121-
fi
122-
done
123-
124-
# linking backwards-compatibility
125-
if [ -n "${!MYSQL_ENV_MYSQL_*}" ]; then
126-
haveConfig=1
127-
# host defaults to "mysql" below if unspecified
128-
: "${WORDPRESS_DB_USER:=${MYSQL_ENV_MYSQL_USER:-root}}"
129-
if [ "$WORDPRESS_DB_USER" = 'root' ]; then
130-
: "${WORDPRESS_DB_PASSWORD:=${MYSQL_ENV_MYSQL_ROOT_PASSWORD:-}}"
131-
else
132-
: "${WORDPRESS_DB_PASSWORD:=${MYSQL_ENV_MYSQL_PASSWORD:-}}"
133-
fi
134-
: "${WORDPRESS_DB_NAME:=${MYSQL_ENV_MYSQL_DATABASE:-}}"
135-
fi
136-
137-
# only touch "wp-config.php" if we have environment-supplied configuration values
138-
if [ "$haveConfig" ]; then
139-
: "${WORDPRESS_DB_HOST:=mysql}"
140-
: "${WORDPRESS_DB_USER:=root}"
141-
: "${WORDPRESS_DB_PASSWORD:=}"
142-
: "${WORDPRESS_DB_NAME:=wordpress}"
143-
: "${WORDPRESS_DB_CHARSET:=utf8}"
144-
: "${WORDPRESS_DB_COLLATE:=}"
145-
146-
# version 4.4.1 decided to switch to windows line endings, that breaks our seds and awks
147-
# https://github.com/docker-library/wordpress/issues/116
148-
# https://github.com/WordPress/WordPress/commit/1acedc542fba2482bab88ec70d4bea4b997a92e4
149-
sed -ri -e 's/\r$//' wp-config*
150-
151-
if [ ! -e wp-config.php ]; then
152-
awk '
153-
/^\/\*.*stop editing.*\*\/$/ && c == 0 {
154-
c = 1
155-
system("cat")
156-
if (ENVIRON["WORDPRESS_CONFIG_EXTRA"]) {
157-
print "// WORDPRESS_CONFIG_EXTRA"
158-
print ENVIRON["WORDPRESS_CONFIG_EXTRA"] "\n"
159-
}
160-
}
161-
{ print }
162-
' wp-config-sample.php > wp-config.php <<'EOPHP'
163-
// If we're behind a proxy server and using HTTPS, we need to alert WordPress of that fact
164-
// see also http://codex.wordpress.org/Administration_Over_SSL#Using_a_Reverse_Proxy
165-
if (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] === 'https') {
166-
$_SERVER['HTTPS'] = 'on';
167-
}
168-
169-
EOPHP
170-
chown "$user:$group" wp-config.php
171-
elif [ -e wp-config.php ] && [ -n "$WORDPRESS_CONFIG_EXTRA" ] && [[ "$(< wp-config.php)" != *"$WORDPRESS_CONFIG_EXTRA"* ]]; then
172-
# (if the config file already contains the requested PHP code, don't print a warning)
173-
echo >&2
174-
echo >&2 'WARNING: environment variable "WORDPRESS_CONFIG_EXTRA" is set, but "wp-config.php" already exists'
175-
echo >&2 ' The contents of this variable will _not_ be inserted into the existing "wp-config.php" file.'
176-
echo >&2 ' (see https://github.com/docker-library/wordpress/issues/333 for more details)'
177-
echo >&2
178-
fi
179-
180-
# see http://stackoverflow.com/a/2705678/433558
181-
sed_escape_lhs() {
182-
echo "$@" | sed -e 's/[]\/$*.^|[]/\\&/g'
183-
}
184-
sed_escape_rhs() {
185-
echo "$@" | sed -e 's/[\/&]/\\&/g'
186-
}
187-
php_escape() {
188-
local escaped="$(php -r 'var_export(('"$2"') $argv[1]);' -- "$1")"
189-
if [ "$2" = 'string' ] && [ "${escaped:0:1}" = "'" ]; then
190-
escaped="${escaped//$'\n'/"' + \"\\n\" + '"}"
191-
fi
192-
echo "$escaped"
193-
}
194-
set_config() {
195-
key="$1"
196-
value="$2"
197-
var_type="${3:-string}"
198-
start="(['\"])$(sed_escape_lhs "$key")\2\s*,"
199-
end="\);"
200-
if [ "${key:0:1}" = '$' ]; then
201-
start="^(\s*)$(sed_escape_lhs "$key")\s*="
202-
end=";"
203-
fi
204-
sed -ri -e "s/($start\s*).*($end)$/\1$(sed_escape_rhs "$(php_escape "$value" "$var_type")")\3/" wp-config.php
205-
}
206-
207-
set_config 'DB_HOST' "$WORDPRESS_DB_HOST"
208-
set_config 'DB_USER' "$WORDPRESS_DB_USER"
209-
set_config 'DB_PASSWORD' "$WORDPRESS_DB_PASSWORD"
210-
set_config 'DB_NAME' "$WORDPRESS_DB_NAME"
211-
set_config 'DB_CHARSET' "$WORDPRESS_DB_CHARSET"
212-
set_config 'DB_COLLATE' "$WORDPRESS_DB_COLLATE"
213-
214-
for unique in "${uniqueEnvs[@]}"; do
215-
uniqVar="WORDPRESS_$unique"
216-
if [ -n "${!uniqVar}" ]; then
217-
set_config "$unique" "${!uniqVar}"
218-
else
219-
# if not specified, let's generate a random value
220-
currentVal="$(sed -rn -e "s/define\(\s*(([\'\"])$unique\2\s*,\s*)(['\"])(.*)\3\s*\);/\4/p" wp-config.php)"
221-
if [ "$currentVal" = 'put your unique phrase here' ]; then
222-
set_config "$unique" "$(head -c1m /dev/urandom | sha1sum | cut -d' ' -f1)"
223-
fi
224-
fi
225-
done
226-
227-
if [ "$WORDPRESS_TABLE_PREFIX" ]; then
228-
set_config '$table_prefix' "$WORDPRESS_TABLE_PREFIX"
229-
fi
230-
231-
if [ "$WORDPRESS_DEBUG" ]; then
232-
set_config 'WP_DEBUG' 1 boolean
233-
fi
234-
235-
if ! TERM=dumb php -- <<'EOPHP'
236-
{!! '<?php' !!}
237-
// database might not exist, so let's try creating it (just to be safe)
238-
239-
$stderr = fopen('php://stderr', 'w');
240-
241-
// https://codex.wordpress.org/Editing_wp-config.php#MySQL_Alternate_Port
242-
// "hostname:port"
243-
// https://codex.wordpress.org/Editing_wp-config.php#MySQL_Sockets_or_Pipes
244-
// "hostname:unix-socket-path"
245-
list($host, $socket) = explode(':', getenv('WORDPRESS_DB_HOST'), 2);
246-
$port = 0;
247-
if (is_numeric($socket)) {
248-
$port = (int) $socket;
249-
$socket = null;
250-
}
251-
$user = getenv('WORDPRESS_DB_USER');
252-
$pass = getenv('WORDPRESS_DB_PASSWORD');
253-
$dbName = getenv('WORDPRESS_DB_NAME');
254-
255-
$maxTries = 10;
256-
do {
257-
$mysql = new mysqli($host, $user, $pass, '', $port, $socket);
258-
if ($mysql->connect_error) {
259-
fwrite($stderr, "\n" . 'MySQL Connection Error: (' . $mysql->connect_errno . ') ' . $mysql->connect_error . "\n");
260-
--$maxTries;
261-
if ($maxTries <= 0) {
262-
exit(1);
263-
}
264-
sleep(3);
265-
}
266-
} while ($mysql->connect_error);
267-
268-
if (!$mysql->query('CREATE DATABASE IF NOT EXISTS `' . $mysql->real_escape_string($dbName) . '`')) {
269-
fwrite($stderr, "\n" . 'MySQL "CREATE DATABASE" Error: ' . $mysql->error . "\n");
270-
$mysql->close();
271-
exit(1);
272-
}
273-
274-
$mysql->close();
275-
EOPHP
276-
then
277-
echo >&2
278-
echo >&2 "WARNING: unable to establish a database connection to '$WORDPRESS_DB_HOST'"
279-
echo >&2 ' continuing anyways (which might have unexpected results)'
280-
echo >&2
281-
fi
282-
fi
10+
if [ ! -z "$CURRENT_USER" ] && [ "$CURRENT_USER" != "0" ]; then
11+
usermod -u $CURRENT_USER kool
12+
fi
28313

284-
# now that we're definitely done writing configuration, let's clear out the relevant envrionment variables (so that stray "phpinfo()" calls don't leak secrets from our code)
285-
for e in "${envs[@]}"; do
286-
unset "$e"
287-
done
14+
# user/group for Wordpress
15+
user=kool
16+
group=kool
17+
uid=$(id -u)
18+
19+
if [ "$1" = "php-fpm" ] || [ "$1" = "supervisord" ]; then
20+
# Original Wordpress Entrypoint - fresh install if none exists
21+
if [ ! -e index.php ] && [ ! -e wp-includes/version.php ]; then
22+
# if the directory exists and WordPress doesn't appear to be installed AND the permissions of it are root:root, let's chown it (likely a Docker-created directory)
23+
if [ "$uid" = '0' ] && [ "$(stat -c '%u:%g' .)" = '0:0' ]; then
24+
chown "$user:$group" .
25+
fi
26+
27+
echo >&2 "WordPress not found in $PWD - copying now..."
28+
if [ -n "$(find -mindepth 1 -maxdepth 1 -not -name wp-content)" ]; then
29+
echo >&2 "WARNING: $PWD is not empty! (copying anyhow)"
30+
fi
31+
sourceTarArgs=(
32+
--create
33+
--file -
34+
--directory /kool/wordpress
35+
--owner "$user" --group "$group"
36+
)
37+
targetTarArgs=(
38+
--extract
39+
--file -
40+
)
41+
if [ "$uid" != '0' ]; then
42+
# avoid "tar: .: Cannot utime: Operation not permitted" and "tar: .: Cannot change mode to rwxr-xr-x: Operation not permitted"
43+
targetTarArgs+=( --no-overwrite-dir )
44+
fi
45+
# loop over "pluggable" content in the source, and if it already exists in the destination, skip it
46+
# https://github.com/docker-library/wordpress/issues/506 ("wp-content" persisted, "akismet" updated, WordPress container restarted/recreated, "akismet" downgraded)
47+
for contentPath in \
48+
/kool/wordpress/.htaccess \
49+
/kool/wordpress/wp-content/*/*/ \
50+
; do
51+
contentPath="${contentPath%/}"
52+
[ -e "$contentPath" ] || continue
53+
contentPath="${contentPath#/kool/wordpress/}" # "wp-content/plugins/akismet", etc.
54+
if [ -e "$PWD/$contentPath" ]; then
55+
echo >&2 "WARNING: '$PWD/$contentPath' exists! (not copying the WordPress version)"
56+
sourceTarArgs+=( --exclude "./$contentPath" )
57+
fi
58+
done
59+
tar "${sourceTarArgs[@]}" . | tar "${targetTarArgs[@]}"
60+
chown -R "$user:$group" /app
61+
echo >&2 "Complete! WordPress has been successfully copied to $PWD"
62+
fi
63+
64+
wpEnvs=( "${!WORDPRESS_@}" )
65+
if [ ! -s wp-config.php ] && [ "${#wpEnvs[@]}" -gt 0 ]; then
66+
for wpConfigDocker in \
67+
wp-config-docker.php \
68+
/kool/wordpress/wp-config-docker.php \
69+
; do
70+
if [ -s "$wpConfigDocker" ]; then
71+
echo >&2 "No 'wp-config.php' found in $PWD, but 'WORDPRESS_...' variables supplied; copying '$wpConfigDocker' (${wpEnvs[*]})"
72+
# using "awk" to replace all instances of "put your unique phrase here" with a properly unique string (for AUTH_KEY and friends to have safe defaults if they aren't specified with environment variables)
73+
awk '
74+
/put your unique phrase here/ {
75+
cmd = "head -c1m /dev/urandom | sha1sum | cut -d\\ -f1"
76+
cmd | getline str
77+
close(cmd)
78+
gsub("put your unique phrase here", str)
79+
}
80+
{ print }
81+
' "$wpConfigDocker" > wp-config.php
82+
if [ "$uid" = '0' ]; then
83+
# attempt to ensure that wp-config.php is owned by the run user
84+
# could be on a filesystem that doesn't allow chown (like some NFS setups)
85+
chown "$user:$group" wp-config.php || true
86+
fi
87+
break
88+
fi
89+
done
90+
fi
28891
fi
28992

290-
exec "$@"
93+
exec /kool/entrypoint "$@"

0 commit comments

Comments
 (0)