英文:
syntax error: unterminated quoted string Docker Certbot
问题
I'm using docker compose. I'm working with a nextjs project. The focus here is setting up the containers specifically to automate server configuration, including SSL certification using Certbot. My objectives are to first get the initial certificate then run a cron job to check if it needs to be renewed. This is a learning exercise for me and would appreciate any insight into my knowledge gap, thank you. I have this docker-compose.yml and the error seems to originate from the Certbot entrypoint. There is no other Certbot configuration beyond this script. Could something else in the container be causing the error? I wasn't able to get the container up and running because it would crash with the error. I don't see any unterminated quoted string.
Here is my docker-compose.yml:
version: "3.9"
services:
app:
build:
context: .
args:
NODE_ENV: production
environment:
NODE_ENV: production
ports:
- "3000:3000"
volumes:
- ./src:/app/src
- ./public:/app/public
- /app/node_modules
container_name: nextjs
nginx:
build: ./nginx
ports:
- "80:80"
- "443:443"
environment:
- DOMAIN_NAMES=${DOCKER_DOMAIN_NAMES}
- CERTIFICATION_EMAIL=${DOCKER_CERTIFICATION_EMAIL}
volumes:
- ./ssl-dhparams.pem:/etc/letsencrypt/ssl-dhparams.pem
- ./nginx/nginx.conf.template:/etc/nginx/nginx.conf.template:ro
- ./nginx/options-ssl-nginx.conf:/etc/letsencrypt/options-ssl-nginx.conf:ro
- ./data/certbot/conf:/etc/letsencrypt
- ./data/certbot/www:/var/www/certbot
depends_on:
- app
certbot:
image: certbot/certbot
entrypoint: "/bin/sh -c 'echo \"0 */12 * * * certbot renew --webroot -w /var/www/certbot --quiet --post-hook 'nginx -s reload'\" | crontab - && crond -f'"
volumes:
- ./data/certbot/conf:/etc/letsencrypt
- ./data/certbot/www:/var/www/certbot
depends_on:
- nginx
Unfortunately, I reached the rate limit with Let's Encrypt, but it will expire tomorrow so I can try again. In the meantime, I'm trying to figure out what I did wrong and if there's a better way to do it. So far I came up with this alternative to instead replace entrypoint with command and use a shell script to check if HTTPS is available and if it fails, then run a renewal:
certbot:
image: certbot/certbot
command: certonly --webroot --webroot-path=/var/www/certbot --email ${DOCKER_CERTIFICATION_EMAIL} --agree-tos --no-eff-email --staging --domains ${DOCKER_DOMAIN_NAMES} --non-interactive
entrypoint: "/bin/sh -c 'chmod +x /scripts/cert_renewal.sh && /scripts/cert_renewal.sh && crond -f'"
volumes:
- ./data/certbot/conf:/etc/letsencrypt
- ./data/certbot/www:/var/www/certbot
- ./nginx:/scripts
depends_on:
- nginx
And this would be the script:
#!/bin/bash
DOMAIN_NAME="www.mydomainhere.com"
WEBROOT_PATH="/var/www/certbot"
# Check if the HTTPS site is available
if ! curl --head --silent --fail https://${DOMAIN_NAME}; then
echo "HTTPS site is not available, running Certbot renewal"
certbot renew --webroot -w ${WEBROOT_PATH} --quiet --post-hook 'nginx -s reload'
fi
# Add this script to crontab if it's not already there
if ! crontab -l | grep -q "${BASH_SOURCE[0]}"; then
(crontab -l ; echo "0 */12 * * * ${BASH_SOURCE[0]}") | crontab -
echo "Added Certbot renewal to crontab"
fi
Any suggestions? Thoughts? What am I doing wrong? Please leave some input, thank you.
英文:
I'm using docker compose. I'm working with a nextjs project. The focus here is setting up the containers specifically to automate server configuration, including SSL certification using Certbot. My objectives are to first get the initial certificate then run a cron job to check if it needs to be renewed. This is a learning exercise for me and would appreciate any insight into my knowledge gap, thank you. I have this docker-compose.yml and the error seems to originate from the Certbot entrypoint. There is no other Certbot configuration beyond this script. Could something else in the container be causing the error? I wasn't able to get the container up and running because it would crash with the error. I don't see any unterminated quoted string.
Here is my docker-compose.yml:
version: "3.9"
services:
app:
build:
context: .
args:
NODE_ENV: production
environment:
NODE_ENV: production
ports:
- "3000:3000"
volumes:
- ./src:/app/src
- ./public:/app/public
- /app/node_modules
container_name: nextjs
nginx:
build: ./nginx
ports:
- "80:80"
- "443:443"
environment:
- DOMAIN_NAMES=${DOCKER_DOMAIN_NAMES}
- CERTIFICATION_EMAIL=${DOCKER_CERTIFICATION_EMAIL}
volumes:
- ./ssl-dhparams.pem:/etc/letsencrypt/ssl-dhparams.pem
- ./nginx/nginx.conf.template:/etc/nginx/nginx.conf.template:ro
- ./nginx/options-ssl-nginx.conf:/etc/letsencrypt/options-ssl-nginx.conf:ro
- ./data/certbot/conf:/etc/letsencrypt
- ./data/certbot/www:/var/www/certbot
depends_on:
- app
certbot:
image: certbot/certbot
entrypoint: "/bin/sh -c 'echo \"0 */12 * * * certbot renew --webroot -w /var/www/certbot --quiet --post-hook 'nginx -s reload'\" | crontab - && crond -f'"
volumes:
- ./data/certbot/conf:/etc/letsencrypt
- ./data/certbot/www:/var/www/certbot
depends_on:
- nginx
Unfortunately I reached the rate limit with letsencrypt, but it will expire tomorrow so I can try again. In the mean time I'm trying to figure out what I did wrong and if there's a better way to do it. So far I came up with this alternative to instead replace entrypoint with command and use a shell script to check if https is available and if it fails then run a renewal:
certbot:
image: certbot/certbot
command: certonly --webroot --webroot-path=/var/www/certbot --email ${DOCKER_CERTIFICATION_EMAIL} --agree-tos --no-eff-email --staging --domains ${DOCKER_DOMAIN_NAMES} --non-interactive
entrypoint: "/bin/sh -c 'chmod +x /scripts/cert_renewal.sh && /scripts/cert_renewal.sh && crond -f'"
volumes:
- ./data/certbot/conf:/etc/letsencrypt
- ./data/certbot/www:/var/www/certbot
- ./nginx:/scripts
depends_on:
- nginx
and this would be the script:
#!/bin/bash
DOMAIN_NAME="www.mydomainhere.com"
WEBROOT_PATH="/var/www/certbot"
# Check if the HTTPS site is available
if ! curl --head --silent --fail https://${DOMAIN_NAME}; then
echo "HTTPS site is not available, running Certbot renewal"
certbot renew --webroot -w ${WEBROOT_PATH} --quiet --post-hook 'nginx -s reload'
fi
# Add this script to crontab if it's not already there
if ! crontab -l | grep -q "${BASH_SOURCE[0]}"; then
(crontab -l ; echo "0 */12 * * * ${BASH_SOURCE[0]}") | crontab -
echo "Added Certbot renewal to crontab"
fi
Any suggestions? Thoughts? What am I doing wrong? Please leave some input, thank you.
答案1
得分: 0
你在 certbot 入口处确实存在一些引用问题;你嵌套了单引号,导致 `--post-hook` 的参数位于包含你的 `sh -c '...'` 调用的单引号之外。将命令行粘贴到 https://www.shellcheck.net/ 可以帮助识别这些问题。
你可以通过利用入口命令的列表形式和 YAML 的块引用运算符,避免一层引用,并尽量减少引号转义的必要性。如果你像这样重写入口点:
entrypoint:
- /bin/sh
- -c
- |
echo "0 */12 * * * certbot renew --webroot -w /var/www/certbot --quiet --post-hook 'nginx -s reload'" |
crontab - && crond -f
事情会变得更加清晰,只需要一个层次的引用。
英文:
There are certainly some quoting problems in your certbot entrypoint; you have nested single quotes that result in the arguments to --post-hook
being outside of the single quotes that enclose your sh -c '...'
invocation. Pasting the command line into https://www.shellcheck.net/ would help identify those issues.
You can avoid a level of quoting -- and minimize the necessity of escaping quotes -- by taking advantage of (a) the list form the of the entrypoint command and (b) YAML's block quote operators. If you rewrite the entrypoint like this:
entrypoint:
- /bin/sh
- -c
- |
echo "0 */12 * * * certbot renew --webroot -w /var/www/certbot --quiet --post-hook 'nginx -s reload'" |
crontab - && crond -f
Things are a bit more clear and only require a single level of quoting.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论