Динамические переменные внутри контейнера¶
Чтобы не хардкодить например имя домена в конфиге nginx(который добавляется в docker image) есть варианты:
server {
listen 80;
server_name ${DOMAIN_NAME};
root /www/${DOMAIN_NAME}/site;
location / {
index index.html;
}
location ~* ^.+\.(jpg|jpeg|gif|png|ico|css|pdf|ppt|txt|bmp|rtf|js|woff)$ {
expires 30d;
}
}
1. использовать встроенный функционал nginx¶
Например в nginx с версии 1.19 есть поддержка environment variables and templates
Entrypoint cкрипты заменяют все переменные, найденные в файлах /etc/nginx/templates/*.template, их соответствующими значениями с использованием envsubst.
Результаты этой подстановки записываются в /etc/nginx/conf.d (требуются права root в контейнере))
Убедитесь, что вы скопировали файл в папку templates и убедитесь, что его расширение - template.
например default.conf.template
docker build -t blog1 -f Dockerfile1 .
docker run -it --name blog1 --rm -e DOMAIN_NAME=test.ru blog1
2.1 свой entrypoint.sh (переназначает дефолтные entrypoint nginx)¶
#!/usr/bin/env sh
set -eu
envsubst '${DOMAIN_NAME}' < /etc/nginx/conf.d/custom.conf.template > /etc/nginx/conf.d/custom.conf
exec "$@"
FROM nginx:alpine
ENV DOMAIN_NAME=$DOMAIN_NAME
COPY custom.conf.template /etc/nginx/conf.d/
COPY ./entrypoint.sh /
RUN chmod +x ./entrypoint.sh
ENTRYPOINT ["/entrypoint.sh"]
CMD ["nginx", "-g", "daemon off;"]
$ docker run -it --name blog1 --rm -e DOMAIN_NAME=test.ru blog1
/docker-entrypoint.sh: /docker-entrypoint.d/ is not empty, will attempt to perform configuration
/docker-entrypoint.sh: Looking for shell scripts in /docker-entrypoint.d/
/docker-entrypoint.sh: Launching /docker-entrypoint.d/10-listen-on-ipv6-by-default.sh
10-listen-on-ipv6-by-default.sh: info: Getting the checksum of /etc/nginx/conf.d/default.conf
10-listen-on-ipv6-by-default.sh: info: Enabled listen on IPv6 in /etc/nginx/conf.d/default.conf
/docker-entrypoint.sh: Sourcing /docker-entrypoint.d/15-local-resolvers.envsh
/docker-entrypoint.sh: Launching /docker-entrypoint.d/20-envsubst-on-templates.sh
20-envsubst-on-templates.sh: Running envsubst on /etc/nginx/templates/custom.conf.template to /etc/nginx/conf.d/custom.conf
/docker-entrypoint.sh: Launching /docker-entrypoint.d/30-tune-worker-processes.sh
/docker-entrypoint.sh: Configuration complete; ready for start up
2024/03/18 03:53:55 [notice] 1#1: using the "epoll" event method
2024/03/18 03:53:55 [notice] 1#1: nginx/1.25.4
2.2 cmd в dockerfile¶
С помощью envsubst мы можем заменить ${VARIABLE} соответствующими значениями переменных окружения.
Поскольку мы не хотим захардкодить значение DOMAIN_NAMe во время сборки, мы подставляем DOMAIN_NAME в момент запуска контейнера. Это может быть не самым простым для чтения, но это простой способ динамического назначения переменной окружения.
FROM nginx:alpine
COPY custom.conf.template /etc/nginx/conf.d/
CMD sh -c "envsubst \"`env | awk -F = '{printf \" \\\\$%s\", $1}'`\" < /etc/nginx/conf.d/custom.conf.template > /etc/nginx/conf.d/custom.conf && nginx -g 'daemon off;'"
3. передать через docker compose¶
...
environment:
- NGINX_DOMAIN_NAME=${HOSTNAME}
- VIRTUAL_HOST=${HOSTNAME}
- LETSENCRYPT_HOST=${HOSTNAME}
- LETSENCRYPT_EMAIL=${EMAIL}
command: bash -c "envsubst '$${DOMAIN_NAME}' < /etc/nginx/conf.d/custom.conf.template > /etc/nginx/conf.d/custom.conf && nginx -g 'daemon off;'"
...
4. через сборку образа, используя ARG с уже установленной переменной¶
удобно когда пользователь контейнера не имеет прав например создать файл в /etc/nginx/conf.d как в варианте #3
через ARG передаем значение переменной
docker build -t blog4 -f Dockerfile4 . --build-arg=DOMAIN_NAME="test.ru"
docker run -it --name blog4 blog4
FROM nginx:1.25-alpine
ARG DOMAIN_NAME='localhost'
ENV DOMAIN_NAME=$DOMAIN_NAME
# Configure nginx
COPY custom.conf /etc/nginx/conf.d/
RUN sed -i 's/${DOMAIN_NAME}/'"$DOMAIN_NAME"'/g' /etc/nginx/conf.d/custom.conf
# Setup document root
RUN mkdir -p /www
# Make sure files/folders needed by the processes are accessable when they run under the nobody user
RUN chown -R nobody.nobody /www && \
chown -R nobody.nobody /run && \
chown -R nobody.nobody /var/cache/nginx && \
chown -R nobody.nobody /var/log/nginx
# Switch to use a non-root user from here on
USER nobody
# Add application
WORKDIR /www
# COPY --chown=nobody site/ /www/$DOMAIN_NAME
# Expose the port nginx is reachable on
EXPOSE 80
STOPSIGNAL SIGTERM
CMD ["nginx", "-g", "daemon off;"]