Как подключить контейнер Varnish к контейнерам PHP-FPM + NGINX? Docker запустился корректно, сайт работает, но логи backendopen пусты.
Бэкэнд исправен (возвращает статус HTTP 200).
лакироватьlog -g raw -i Backend_health
0 Backend_health - default Still healthy 4---X-RH 7 5 10 0.048069 0.065633 "HTTP/1.1 200 OK"
Из контейнера http (nginx) я вижу запрос в журналах Docker.
логи докера http
[10/Sep/2021:17:24:01 +0000] "GET /health_check.php HTTP/1.1" 200 5 "-" "-"
Но бэкэнд-соединение не открывается, журналы пусты, проверено с помощью:лакирлог -i бэкэндоткрытыйкоманда. Я попробовал решение с этого сайта, но не работает:Php+Nginx+Varnish на docker-compose, ubuntu18.
docker-compose.yml
http:
build:
context: docker/http
container_name: http
ports:
- 80:80
- 443:443
depends_on:
- php
volumes:
- ./project:/var/www/project
php:
build:
context: docker/php
container_name: php
working_dir: /var/www/project
volumes:
- ./project:/var/www/project
varnish:
build:
context: docker/varnish
container_name: varnish
ports:
- 6081:6081
- 6082:6082
Конфигурация VCL:
vcl 4.0;
import std;
backend default {
.host = "http";
.port = "80";
.first_byte_timeout = 600s;
.probe = {
#.url = "/health_check.php";
.request =
"GET /health_check.php HTTP/1.1"
"Host: http"
"Connection: close";
.timeout = 2s;
.interval = 5s;
.window = 10;
.threshold = 5;
}
}
acl purge {
"http";
}
sub vcl_recv {
if (req.restarts > 0) {
set req.hash_always_miss = true;
}
if (req.method == "PURGE") {
if (client.ip !~ purge) {
return (synth(405, "Method not allowed"));
}
# To use the X-Pool header for purging varnish during automated deployments, make sure the X-Pool header
# has been added to the response in your backend server config. This is used, for example, by the
# capistrano-magento2 gem for purging old content from varnish during it's deploy routine.
if (!req.http.X-Magento-Tags-Pattern && !req.http.X-Pool) {
return (synth(400, "X-Magento-Tags-Pattern or X-Pool header required"));
}
if (req.http.X-Magento-Tags-Pattern) {
ban("obj.http.X-Magento-Tags ~ " + req.http.X-Magento-Tags-Pattern);
}
if (req.http.X-Pool) {
ban("obj.http.X-Pool ~ " + req.http.X-Pool);
}
return (synth(200, "Purged"));
}
if (req.method != "GET" &&
req.method != "HEAD" &&
req.method != "PUT" &&
req.method != "POST" &&
req.method != "TRACE" &&
req.method != "OPTIONS" &&
req.method != "DELETE") {
/* Non-RFC2616 or CONNECT which is weird. */
return (pipe);
}
# We only deal with GET and HEAD by default
if (req.method != "GET" && req.method != "HEAD") {
return (pass);
}
# Bypass shopping cart and checkout
if (req.url ~ "/checkout") {
return (pass);
}
# Bypass health check requests
if (req.url ~ "/pub/health_check.php") {
return (pass);
}
# Set initial grace period usage status
set req.http.grace = "none";
# normalize url in case of leading HTTP scheme and domain
set req.url = regsub(req.url, "^http[s]?://", "");
# collect all cookies
std.collect(req.http.Cookie);
# Compression filter. See https://www.varnish-cache.org/trac/wiki/FAQ/Compression
if (req.http.Accept-Encoding) {
if (req.url ~ "\.(jpg|jpeg|png|gif|gz|tgz|bz2|tbz|mp3|ogg|swf|flv)$") {
# No point in compressing these
unset req.http.Accept-Encoding;
} elsif (req.http.Accept-Encoding ~ "gzip") {
set req.http.Accept-Encoding = "gzip";
} elsif (req.http.Accept-Encoding ~ "deflate" && req.http.user-agent !~ "MSIE") {
set req.http.Accept-Encoding = "deflate";
} else {
# unknown algorithm
unset req.http.Accept-Encoding;
}
}
# Remove all marketing get parameters to minimize the cache objects
if (req.url ~ "(\?|&)(gclid|cx|ie|cof|siteurl|zanpid|origin|fbclid|mc_[a-z]+|utm_[a-z]+|_bta_[a-z]+)=") {
set req.url = regsuball(req.url, "(gclid|cx|ie|cof|siteurl|zanpid|origin|fbclid|mc_[a-z]+|utm_[a-z]+|_bta_[a-z]+)=[-_A-z0-9+()%.]+&?", "");
set req.url = regsub(req.url, "[?|&]+$", "");
}
# Static files caching
if (req.url ~ "^/(pub/)?(media|static)/") {
# Static files should not be cached by default
return (pass);
# But if you use a few locales and don't use CDN you can enable caching static files by commenting previous line (#return (pass);) and uncommenting next 3 lines
#unset req.http.Https;
#unset req.http.X-Forwarded-Proto;
#unset req.http.Cookie;
}
# Authenticated GraphQL requests should not be cached by default
if (req.url ~ "/graphql" && req.http.Authorization ~ "^Bearer") {
return (pass);
}
return (hash);
}
sub vcl_hash {
if (req.http.cookie ~ "X-Magento-Vary=") {
hash_data(regsub(req.http.cookie, "^.*?X-Magento-Vary=([^;]+);*.*$", "\1"));
}
# To make sure http users don't see ssl warning
if (req.http.X-Forwarded-Proto) {
hash_data(req.http.X-Forwarded-Proto);
}
if (req.url ~ "/graphql") {
call process_graphql_headers;
}
}
sub process_graphql_headers {
if (req.http.Store) {
hash_data(req.http.Store);
}
if (req.http.Content-Currency) {
hash_data(req.http.Content-Currency);
}
}
sub vcl_backend_response {
set beresp.grace = 3d;
if (beresp.http.content-type ~ "text") {
set beresp.do_esi = true;
}
if (bereq.url ~ "\.js$" || beresp.http.content-type ~ "text") {
set beresp.do_gzip = true;
}
if (beresp.http.X-Magento-Debug) {
set beresp.http.X-Magento-Cache-Control = beresp.http.Cache-Control;
}
# cache only successfully responses and 404s
if (beresp.status != 200 && beresp.status != 404) {
set beresp.ttl = 0s;
set beresp.uncacheable = true;
return (deliver);
} elsif (beresp.http.Cache-Control ~ "private") {
set beresp.uncacheable = true;
set beresp.ttl = 86400s;
return (deliver);
}
# validate if we need to cache it and prevent from setting cookie
if (beresp.ttl > 0s && (bereq.method == "GET" || bereq.method == "HEAD")) {
unset beresp.http.set-cookie;
}
# If page is not cacheable then bypass varnish for 2 minutes as Hit-For-Pass
if (beresp.ttl <= 0s ||
beresp.http.Surrogate-control ~ "no-store" ||
(!beresp.http.Surrogate-Control &&
beresp.http.Cache-Control ~ "no-cache|no-store") ||
beresp.http.Vary == "*") {
# Mark as Hit-For-Pass for the next 2 minutes
set beresp.ttl = 120s;
set beresp.uncacheable = true;
}
return (deliver);
}
sub vcl_deliver {
if (resp.http.X-Magento-Debug) {
if (resp.http.x-varnish ~ " ") {
set resp.http.X-Magento-Cache-Debug = "HIT";
set resp.http.Grace = req.http.grace;
} else {
set resp.http.X-Magento-Cache-Debug = "MISS";
}
} else {
unset resp.http.Age;
}
# Not letting browser to cache non-static files.
if (resp.http.Cache-Control !~ "private" && req.url !~ "^/(pub/)?(media|static)/") {
set resp.http.Pragma = "no-cache";
set resp.http.Expires = "-1";
set resp.http.Cache-Control = "no-store, no-cache, must-revalidate, max-age=0";
}
unset resp.http.X-Magento-Debug;
unset resp.http.X-Magento-Tags;
unset resp.http.X-Powered-By;
unset resp.http.Server;
unset resp.http.X-Varnish;
unset resp.http.Via;
unset resp.http.Link;
}
sub vcl_hit {
if (obj.ttl >= 0s) {
# Hit within TTL period
return (deliver);
}
if (std.healthy(req.backend_hint)) {
if (obj.ttl + 300s > 0s) {
# Hit after TTL expiration, but within grace period
set req.http.grace = "normal (healthy server)";
return (deliver);
} else {
# Hit after TTL and grace expiration
return (restart);
}
} else {
# server is not healthy, retrieve from cache
set req.http.grace = "unlimited (unhealthy server)";
return (deliver);
}
}
решение1
Попробуйте запустить его varnishlog -g request -q "ReqUrl eq '/'"
, чтобы увидеть, что происходит при запросе домашней страницы.
Если выполнить эту команду, когда кэш пуст, мы должны увидеть попытку Varnish подключиться к бэкэнду.
Пожалуйста, поделитесь выводом VSL здесь, и я помогу.
ОБНОВЛЯТЬ
Я заметил в вашем docker-compose.yml
файле, что ваш http
контейнер настроен на обработку трафика на портах 80
и 443
.
Проблема
Контейнер varnish
прослушивает порты 6081
& 6082
. Если вы не направляете трафик напрямую на порт, 6081
то совершенно очевидно, что Varnish не получает никаких запросов.
Решение
Пожалуйста, убедитесь, что ваш контейнер Varnish также прослушивает входящий трафик на порту 80
. В вашем VCL вы можете указать порт 80
на http
контейнере.
Но что касается раскрытия портов, вы можете захотеть перенаправить http
порт вашего контейнера 80
на 8080
. Это позволит избежать конфликта с Varnish, 80
также находящимся в порту.
Вы также можете напрямую запустить официальныйЛакированное изображениевместо того, чтобы строить его самостоятельно.
Вот руководство по запуску и настройке официального образа Docker:https://www.varnish-software.com/developers/tutorials/running-varnish-docker/
завершение TLS
В настоящее время порт 443
связан с вашим http
контейнером. Если вы можете обрабатывать терминацию TLS там и проксировать HTTPS-запросы в Varnish, это нормально.
Если нет, то можете бежатьконтейнер Hitchкоторый выполняет завершение TLS для вас.