{"id":271,"date":"2026-10-17T10:10:45","date_gmt":"2026-10-17T08:10:45","guid":{"rendered":"https:\/\/www.cisilino.com\/?p=271"},"modified":"2026-10-29T20:00:39","modified_gmt":"2026-10-29T19:00:39","slug":"mysql-5-7-docker-nftables-firewall","status":"publish","type":"post","link":"https:\/\/www.cisilino.com\/en\/2026\/10\/17\/mysql-5-7-docker-nftables-firewall\/","title":{"rendered":"MySQL 5.7 in Docker protected with nftables"},"content":{"rendered":"<h2 class=\"wp-block-heading\">Background<\/h2>\n<p>We needed <strong>MySQL 5.7 in Docker<\/strong>, a legacy database on a server that otherwise runs a recent distribution. Some legacy applications are not compatible with MySQL 8. The reasons: a change of default authentication plugin, stricter SQL modes, new reserved words. Migrating them quickly was not an option.<\/p>\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/www.cisilino.com\/wp-content\/uploads\/2026\/10\/mysql-5-7-docker-nftables-firewall.webp\" alt=\"MySQL 5.7 in Docker: a database inside a box, surrounded by an orange dashed border, with a circle and a bar in front\" width=\"1200\" height=\"630\"\/><\/figure>\n<p>Installing such an old version directly on the host brings several problems. The official repositories of current distributions no longer offer it. Third-party packages risk conflicting with the rest of the system. An OS upgrade could break it.<\/p>\n<p>So we decided to <strong>isolate it in a Docker container<\/strong>: the host stays clean and up to date. The database version is fixed and reproducible. Data and configuration live in a folder that is easy to back up and move.<\/p>\n<p>This article tells how we set it up and, above all, the obstacles we met along the way. First the unintentional exposure of port 3306, then an iptables error at reboot. Last, writing a firewall with <strong>nftables<\/strong> that lets through only authorised IPs.<\/p>\n<blockquote class=\"wp-block-quote\">\n<p><strong>Note:<\/strong> MySQL 5.7 reached end of life (EOL) in October 2023 and no longer receives security patches. It is a stopgap: the goal remains to migrate to MySQL 8.x or MariaDB. That is exactly why it is even more important not to leave it exposed.<\/p>\n<\/blockquote>\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n<h2 class=\"wp-block-heading\">1. Folder structure<\/h2>\n<pre class=\"wp-block-code\"><code>\/opt\/mysql57\/\n\u251c\u2500\u2500 docker-compose.yml\n\u251c\u2500\u2500 .env\n\u251c\u2500\u2500 conf.d\/        # configurazioni personalizzate (my.cnf aggiuntivi)\n\u251c\u2500\u2500 data\/          # dati del database (volume persistente)\n\u2514\u2500\u2500 logs\/\n<\/code><\/pre>\n<p>The <code>.env<\/code> file holds the credentials, so they don&#8217;t end up in the compose file:<\/p>\n<pre class=\"wp-block-code\"><code>TZ=Europe\/Rome\nMYSQL_ROOT_PASSWORD=una_password_molto_lunga_e_casuale\nMYSQL_DATABASE=nome_db\nMYSQL_USER=nome_utente\nMYSQL_PASSWORD=altra_password_robusta\n<\/code><\/pre>\n<p>Protect it with <code>chmod 600 .env<\/code>.<\/p>\n<h2 class=\"wp-block-heading\">2. MySQL 5.7 in Docker: the docker-compose.yml<\/h2>\n<pre class=\"wp-block-code\"><code>services:\n  mysql57:\n    image: mysql:5.7\n    container_name: mysql57\n    restart: unless-stopped\n    env_file:\n      - .env\n    ports:\n      - \"3306:3306\"\n    environment:\n      TZ: \"${TZ:-Europe\/Rome}\"\n      MYSQL_ROOT_PASSWORD: \"${MYSQL_ROOT_PASSWORD}\"\n      MYSQL_DATABASE: \"${MYSQL_DATABASE}\"\n      MYSQL_USER: \"${MYSQL_USER}\"\n      MYSQL_PASSWORD: \"${MYSQL_PASSWORD}\"\n    command:\n      - --default-authentication-plugin=mysql_native_password\n    volumes:\n      - .\/data:\/var\/lib\/mysql\n      - .\/conf.d:\/etc\/mysql\/conf.d:ro\n      - .\/logs:\/var\/log\/mysql\n    healthcheck:\n      test: &#91;\"CMD-SHELL\", \"mysqladmin ping -h 127.0.0.1 -uroot -p$$MYSQL_ROOT_PASSWORD --silent\"]\n      interval: 20s\n      timeout: 5s\n      retries: 10\n      start_period: 45s\n    ulimits:\n      nofile:\n        soft: 65535\n        hard: 65535\n<\/code><\/pre>\n<p>A few choices worth noting:<\/p>\n<ul class=\"wp-block-list\">\n<li><strong><code>restart: unless-stopped<\/code><\/strong>: the database restarts by itself after a server reboot.<\/li>\n<li><strong>Bind-mount volumes<\/strong>: data, configuration and logs are on the host, so backups and migrations are simple folder copies.<\/li>\n<li><strong>Healthcheck<\/strong>: lets other services wait until MySQL is really ready (<code>$$<\/code> makes the variable expand inside the container and not in Compose).<\/li>\n<li><strong><code>ulimits nofile<\/code><\/strong>: avoids the &#8220;too many open files&#8221; error under load.<\/li>\n<\/ul>\n<h2 class=\"wp-block-heading\">3. First problem: the port is open to the whole world<\/h2>\n<p>The line <code>- \"3306:3306\"<\/code> is equivalent to <code>0.0.0.0:3306:3306<\/code>. Docker publishes the port on <strong>all interfaces<\/strong> of the host, including the public one.<\/p>\n<p>The most insidious part is that Docker writes its own rules straight into the kernel firewall. These are evaluated before those of UFW or firewalld. Having a firewall running is <strong>not enough<\/strong>: the port stays reachable. Docker&#8217;s own documentation on <a href=\"https:\/\/docs.docker.com\/engine\/network\/packet-filtering-firewalls\/\" target=\"_blank\" rel=\"noopener\">packet filtering and firewalls<\/a> describes this behaviour.<\/p>\n<p>The possible approaches are:<\/p>\n<ol class=\"wp-block-list\">\n<li><strong>Localhost only<\/strong>: <code>\"127.0.0.1:3306:3306\"<\/code>, if the database is only used by the host or through an SSH tunnel.<\/li>\n<li><strong>No published port<\/strong>: if the clients are other containers, a shared Docker network is enough.<\/li>\n<li><strong>Specific IP<\/strong>: publish only on an address of a private network\/VPN.<\/li>\n<li><strong>Public port with IP filtering<\/strong>: our case, because an external client (a phpMyAdmin instance on another server) has to be able to connect.<\/li>\n<\/ol>\n<p>For case 4 you need a firewall that correctly filters the traffic of the ports published by Docker.<\/p>\n<h2 class=\"wp-block-heading\">4. Second problem: an iptables error at startup<\/h2>\n<p>After touching the firewall, <code>docker compose up<\/code> returned:<\/p>\n<pre class=\"wp-block-code\"><code>failed to create network mysql57_default: Error response from daemon:\nFailed to Setup IP tables: Unable to enable ACCEPT OUTGOING rule:\n(iptables failed: iptables --wait -t filter -A DOCKER-FORWARD -i br-... -j ACCEPT:\niptables: No chain\/target\/match by that name.\n<\/code><\/pre>\n<p>The error doesn&#8217;t depend on the compose file: the <code>DOCKER-FORWARD<\/code> chain (introduced in recent Docker versions) no longer existed. It had been deleted by something that cleaned up the rules <strong>after<\/strong> the daemon started. Restarting Docker (<code>systemctl restart docker<\/code>) recreates it, but the problem comes back until the real culprit is removed.<\/p>\n<h3 class=\"wp-block-heading\">The culprit: <code>flush ruleset<\/code><\/h3>\n<p>Our <code>\/etc\/nftables.conf<\/code> began with:<\/p>\n<pre class=\"wp-block-code\"><code>flush ruleset\n<\/code><\/pre>\n<p>This command deletes <strong>all<\/strong> nftables tables, including those created by Docker. On top of that the file contained a static copy of Docker&#8217;s rules. The bridge name (<code>br-278550235c3f<\/code>) and the container IP (<code>172.18.0.2<\/code>) were written by hand. But the bridge name changes every time the Compose network is recreated, so the copy immediately became obsolete. The <code>ip nat<\/code> table also clashed with the one managed by Docker.<\/p>\n<p><strong>Golden rule:<\/strong> with Docker, in the nftables file you don&#8217;t use <code>flush ruleset<\/code> and you don&#8217;t copy its rules. You manage only your own firewall, in dedicated tables.<\/p>\n<h2 class=\"wp-block-heading\">5. The nftables firewall for MySQL 5.7 in Docker<\/h2>\n<p>The principle is this: the ports published by Docker are rewritten with DNAT and then forwarded by the host to the container, so they go through the <strong><code>forward<\/code><\/strong> chain, not <code>input<\/code>. A <code>drop<\/code> rule in a chain of ours, <code>forward<\/code>, with a slightly lower priority (so evaluated first). It drops the packet regardless of Docker&#8217;s <code>accept<\/code> rules.<\/p>\n<p>To avoid touching other people&#8217;s tables we use the <code>table ...<\/code> + <code>delete table ...<\/code> pattern: it makes the file re-runnable without errors and without <code>flush<\/code>.<\/p>\n<p><code>\/etc\/nftables.conf<\/code>:<\/p>\n<pre class=\"wp-block-code\"><code>#!\/usr\/sbin\/nft -f\n\n# NIENTE \"flush ruleset\": cancellerebbe anche le tabelle di Docker\n\n# ---------------- firewall host ----------------\ntable inet filter\ndelete table inet filter\n\ntable inet filter {\n\n    chain input {\n        type filter hook input priority filter; policy drop;\n        ct state established,related accept\n        iifname \"lo\" accept\n        ip6 nexthdr icmpv6 accept\n        iifname \"enp7s0\" accept                       # rete privata\n        ip saddr 203.0.113.20 tcp dport 22 accept     # SSH da host fidato\n        ip saddr 203.0.113.30 tcp dport 22 accept     # SSH da VPN\n        ip saddr 203.0.113.20 icmp type echo-request accept\n        tcp dport { 80, 443 } accept\n    }\n\n    chain output {\n        type filter hook output priority filter; policy accept;\n    }\n}\n\n# ---------------- guardia MySQL (porta pubblicata da Docker) ----------------\ntable ip mysql_guard\ndelete table ip mysql_guard\n\ntable ip mysql_guard {\n    set allowed {\n        type ipv4_addr\n        flags interval\n        elements = {\n            203.0.113.10        # phpMyAdmin\n        }\n    }\n\n    chain forward {\n        type filter hook forward priority filter - 5; policy accept;\n        iifname \"enp7s0\" accept\n        ct status dnat tcp dport 3306 ip saddr @allowed accept\n        ct status dnat tcp dport 3306 counter drop\n    }\n}\n<\/code><\/pre>\n<p>How the guard works:<\/p>\n<ul class=\"wp-block-list\">\n<li><code>ct status dnat<\/code> selects only packets that went through DNAT, that is those headed to the ports published by Docker.<\/li>\n<li>The first rule accepts whoever is in the <code>allowed<\/code> set; the second drops everyone else and counts them (<code>counter<\/code>).<\/li>\n<li>Local traffic (<code>127.0.0.1<\/code>) and traffic between containers on the same network doesn&#8217;t go through the router&#8217;s forward. So it isn&#8217;t touched.<\/li>\n<\/ul>\n<blockquote class=\"wp-block-quote\">\n<p><strong>Compatibility:<\/strong> in a first version we used <code>ct original proto-dst 3306<\/code>, but some versions of <code>nft<\/code> answer with <em>&#8220;Can&#8217;t parse symbolic invalid expressions&#8221;<\/em>. In the <code>forward<\/code> hook the DNAT has already happened and the container port matches the published one (<code>3306:3306<\/code>). So <code>tcp dport 3306<\/code> combined with <code>ct status dnat<\/code> is equivalent and works everywhere. If you change the mapping (e.g. <code>3307:3306<\/code>), the rule must be adapted to the internal port.<\/p>\n<\/blockquote>\n<h3 class=\"wp-block-heading\">Applying the changes without locking yourself out<\/h3>\n<p>Keep a spare SSH session open, then:<\/p>\n<pre class=\"wp-block-code\"><code>nft -c -f \/etc\/nftables.conf     # solo verifica della sintassi\nnft delete table ip nat          # una tantum: elimina la vecchia copia statica\nnft -f \/etc\/nftables.conf\nsystemctl restart docker         # Docker ricrea le sue tabelle pulite\ncd \/opt\/mysql57 &amp;&amp; docker compose up -d\n<\/code><\/pre>\n<p>For loading at boot, make sure the service is enabled (<code>systemctl enable --now nftables<\/code>) and that <code>\/etc\/nftables.conf<\/code> does not contain <code>flush ruleset<\/code>.<\/p>\n<h3 class=\"wp-block-heading\">Managing IPs at runtime<\/h3>\n<pre class=\"wp-block-code\"><code>nft add element ip mysql_guard allowed { 203.0.113.50 }\nnft delete element ip mysql_guard allowed { 203.0.113.50 }\n<\/code><\/pre>\n<p>To make it permanent, also update the set in the file.<\/p>\n<h2 class=\"wp-block-heading\">6. Verification<\/h2>\n<p>From the authorised server:<\/p>\n<pre class=\"wp-block-code\"><code>nc -zv IP_PUBBLICO_DB 3306        # deve rispondere \"succeeded\"\n<\/code><\/pre>\n<p>From any other IP:<\/p>\n<pre class=\"wp-block-code\"><code>nmap -Pn -p 3306 IP_PUBBLICO_DB   # deve risultare \"filtered\" \/ timeout\n<\/code><\/pre>\n<p>On the server, the drop rule&#8217;s counter must grow with every unauthorised attempt:<\/p>\n<pre class=\"wp-block-code\"><code>nft list chain ip mysql_guard forward\nss -tlnp | grep 3306\n<\/code><\/pre>\n<h2 class=\"wp-block-heading\">7. Second barrier: the MySQL users<\/h2>\n<p>The firewall doesn&#8217;t replace database permissions. Create the user with the host limited to the client&#8217;s IP:<\/p>\n<pre class=\"wp-block-code\"><code>CREATE USER 'pma_user'@'203.0.113.10' IDENTIFIED BY 'password_robusta';\nGRANT ALL ON nome_db.* TO 'pma_user'@'203.0.113.10';\nFLUSH PRIVILEGES;\n<\/code><\/pre>\n<p>If the TCP connection succeeds but MySQL answers <code>Access denied<\/code>, the problem is here and not in the firewall.<\/p>\n<h2 class=\"wp-block-heading\">8. Things to remember about MySQL 5.7 in Docker<\/h2>\n<ul class=\"wp-block-list\">\n<li><strong>Docker and the host firewall don&#8217;t ignore each other<\/strong>. Understanding which chain the traffic goes through (<code>input<\/code> or <code>forward<\/code>) is the key to everything.<\/li>\n<li><strong>Never <code>flush ruleset<\/code><\/strong> on a host with Docker; use dedicated tables.<\/li>\n<li><strong>Don&#8217;t copy the rules generated by Docker<\/strong> into your own files: bridge names and IPs change.<\/li>\n<li>If you have already exposed the port, check the logs in <code>.\/logs<\/code> and consider <strong>changing the passwords<\/strong>, especially root&#8217;s.<\/li>\n<li>Where possible, prefer a <strong>VPN (WireGuard) or SSH tunnel<\/strong> to exposing a database publicly.<\/li>\n<li>Plan the <strong>migration<\/strong> from MySQL 5.7 to a supported version.<\/li>\n<\/ul>\n<p>Do you have questions or a different solution to the same problem? Write it in the comments. If you run MySQL on Debian, see also <a href=\"https:\/\/www.cisilino.com\/en\/2026\/10\/13\/mysql-wont-start-debian-12\/\">MySQL won&#8217;t start after a Debian 12 upgrade<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>How to run MySQL 5.7 in Docker on a modern server without exposing it to the internet: docker-compose, a closed port and an nftables firewall.<\/p>\n","protected":false},"author":1,"featured_media":757,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"wpai_generated_summary":"","footnotes":""},"categories":[361],"tags":[308,328,292,312],"class_list":["post-271","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-servers-databases","tag-docker-en","tag-firewall-en","tag-mysql-en","tag-nftables-en"],"aioseo_notices":[],"aioseo_head":"\n\t\t<!-- All in One SEO 5.0.4 - aioseo.com -->\n\t<meta name=\"description\" content=\"How to run MySQL 5.7 in Docker on a modern server without exposing it to the internet: docker-compose, a closed port and an nftables firewall.\" \/>\n\t<meta name=\"robots\" content=\"max-image-preview:large\" \/>\n\t<meta name=\"author\" content=\"matteocisilino\"\/>\n\t<meta name=\"google-site-verification\" content=\"_A-1f0dO30IDVHfP9muflI8kHQs-H4YOi8WLUkYzuLE\" \/>\n\t<link rel=\"canonical\" href=\"https:\/\/www.cisilino.com\/en\/2026\/10\/17\/mysql-5-7-docker-nftables-firewall\/\" \/>\n\t\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.4\" \/>\n\t\t<meta property=\"og:locale\" content=\"en_GB\" \/>\n\t\t<meta property=\"og:site_name\" content=\"Matteo Cisilino - Guide su WordPress, server e sicurezza\" \/>\n\t\t<meta property=\"og:type\" content=\"article\" \/>\n\t\t<meta property=\"og:title\" content=\"MySQL 5.7 in Docker protected with nftables\" \/>\n\t\t<meta property=\"og:description\" content=\"How to run MySQL 5.7 in Docker on a modern server without exposing it to the internet: docker-compose, a closed port and an nftables firewall.\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/www.cisilino.com\/en\/2026\/10\/17\/mysql-5-7-docker-nftables-firewall\/\" \/>\n\t\t<meta property=\"og:image\" content=\"https:\/\/www.cisilino.com\/wp-content\/uploads\/2026\/10\/mysql-5-7-docker-nftables-firewall.webp\" \/>\n\t\t<meta property=\"og:image:secure_url\" content=\"https:\/\/www.cisilino.com\/wp-content\/uploads\/2026\/10\/mysql-5-7-docker-nftables-firewall.webp\" \/>\n\t\t<meta property=\"og:image:width\" content=\"1200\" \/>\n\t\t<meta property=\"og:image:height\" content=\"630\" \/>\n\t\t<meta property=\"article:published_time\" content=\"2026-10-17T08:10:45+00:00\" \/>\n\t\t<meta property=\"article:modified_time\" content=\"2026-10-29T19:00:39+00:00\" \/>\n\t\t<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n\t\t<meta name=\"twitter:title\" content=\"MySQL 5.7 in Docker protected with nftables\" \/>\n\t\t<meta name=\"twitter:description\" content=\"How to run MySQL 5.7 in Docker on a modern server without exposing it to the internet: docker-compose, a closed port and an nftables firewall.\" \/>\n\t\t<meta name=\"twitter:image\" content=\"https:\/\/www.cisilino.com\/wp-content\/uploads\/2026\/10\/mysql-5-7-docker-nftables-firewall.webp\" \/>\n\t\t<script type=\"application\/ld+json\" class=\"aioseo-schema\">\n\t\t\t{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"BlogPosting\",\"@id\":\"https:\\\/\\\/www.cisilino.com\\\/en\\\/2026\\\/10\\\/17\\\/mysql-5-7-docker-nftables-firewall\\\/#blogposting\",\"name\":\"MySQL 5.7 in Docker protected with nftables\",\"headline\":\"MySQL 5.7 in Docker protected with nftables\",\"author\":{\"@id\":\"https:\\\/\\\/www.cisilino.com\\\/en\\\/author\\\/matteocisilino\\\/#author\"},\"publisher\":{\"@id\":\"https:\\\/\\\/www.cisilino.com\\\/en\\\/#organization\"},\"image\":{\"@type\":\"ImageObject\",\"url\":\"https:\\\/\\\/www.cisilino.com\\\/wp-content\\\/uploads\\\/2026\\\/10\\\/mysql-5-7-docker-nftables-firewall.webp\",\"width\":1200,\"height\":630,\"caption\":\"MySQL 5.7 in Docker: a database inside a box, surrounded by an orange dashed border, with a circle and a bar in front\"},\"datePublished\":\"2026-10-17T10:10:45+02:00\",\"dateModified\":\"2026-10-29T20:00:39+01:00\",\"inLanguage\":\"en-GB\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/www.cisilino.com\\\/en\\\/2026\\\/10\\\/17\\\/mysql-5-7-docker-nftables-firewall\\\/#webpage\"},\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.cisilino.com\\\/en\\\/2026\\\/10\\\/17\\\/mysql-5-7-docker-nftables-firewall\\\/#webpage\"},\"articleSection\":\"Servers and databases, Docker, firewall, MySQL, nftables\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/www.cisilino.com\\\/en\\\/2026\\\/10\\\/17\\\/mysql-5-7-docker-nftables-firewall\\\/#breadcrumblist\",\"itemListElement\":[{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/www.cisilino.com\\\/en\\\/#listItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/www.cisilino.com\\\/en\\\/\",\"nextItem\":{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/www.cisilino.com\\\/en\\\/category\\\/servers-databases\\\/#listItem\",\"name\":\"Servers and databases\"}},{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/www.cisilino.com\\\/en\\\/category\\\/servers-databases\\\/#listItem\",\"position\":2,\"name\":\"Servers and databases\",\"item\":\"https:\\\/\\\/www.cisilino.com\\\/en\\\/category\\\/servers-databases\\\/\",\"nextItem\":{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/www.cisilino.com\\\/en\\\/2026\\\/10\\\/17\\\/mysql-5-7-docker-nftables-firewall\\\/#listItem\",\"name\":\"MySQL 5.7 in Docker protected with nftables\"},\"previousItem\":{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/www.cisilino.com\\\/en\\\/#listItem\",\"name\":\"Home\"}},{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/www.cisilino.com\\\/en\\\/2026\\\/10\\\/17\\\/mysql-5-7-docker-nftables-firewall\\\/#listItem\",\"position\":3,\"name\":\"MySQL 5.7 in Docker protected with nftables\",\"previousItem\":{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/www.cisilino.com\\\/en\\\/category\\\/servers-databases\\\/#listItem\",\"name\":\"Servers and databases\"}}]},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/www.cisilino.com\\\/en\\\/#organization\",\"name\":\"Matteo Cisilino\",\"description\":\"Guide su WordPress, server e sicurezza\",\"url\":\"https:\\\/\\\/www.cisilino.com\\\/en\\\/\",\"logo\":{\"@type\":\"ImageObject\",\"url\":\"https:\\\/\\\/www.cisilino.com\\\/wp-content\\\/uploads\\\/2026\\\/10\\\/logo-cisilino-512.png\",\"@id\":\"https:\\\/\\\/www.cisilino.com\\\/en\\\/2026\\\/10\\\/17\\\/mysql-5-7-docker-nftables-firewall\\\/#organizationLogo\",\"width\":512,\"height\":512,\"caption\":\"Logo: un cerchio a sinistra che si divide in cerchi pi\\u00f9 piccoli\"},\"image\":{\"@id\":\"https:\\\/\\\/www.cisilino.com\\\/en\\\/2026\\\/10\\\/17\\\/mysql-5-7-docker-nftables-firewall\\\/#organizationLogo\"}},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/www.cisilino.com\\\/en\\\/author\\\/matteocisilino\\\/#author\",\"url\":\"https:\\\/\\\/www.cisilino.com\\\/en\\\/author\\\/matteocisilino\\\/\",\"name\":\"matteocisilino\",\"image\":{\"@type\":\"ImageObject\",\"@id\":\"https:\\\/\\\/www.cisilino.com\\\/en\\\/2026\\\/10\\\/17\\\/mysql-5-7-docker-nftables-firewall\\\/#authorImage\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/639872265f0661e8aee8924ba9d756b00ea816f8286fab99a5116c729d49618f?s=96&d=mm&r=g\",\"width\":96,\"height\":96,\"caption\":\"matteocisilino\"}},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/www.cisilino.com\\\/en\\\/2026\\\/10\\\/17\\\/mysql-5-7-docker-nftables-firewall\\\/#webpage\",\"url\":\"https:\\\/\\\/www.cisilino.com\\\/en\\\/2026\\\/10\\\/17\\\/mysql-5-7-docker-nftables-firewall\\\/\",\"name\":\"MySQL 5.7 in Docker protected with nftables\",\"description\":\"How to run MySQL 5.7 in Docker on a modern server without exposing it to the internet: docker-compose, a closed port and an nftables firewall.\",\"inLanguage\":\"en-GB\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.cisilino.com\\\/en\\\/#website\"},\"breadcrumb\":{\"@id\":\"https:\\\/\\\/www.cisilino.com\\\/en\\\/2026\\\/10\\\/17\\\/mysql-5-7-docker-nftables-firewall\\\/#breadcrumblist\"},\"author\":{\"@id\":\"https:\\\/\\\/www.cisilino.com\\\/en\\\/author\\\/matteocisilino\\\/#author\"},\"creator\":{\"@id\":\"https:\\\/\\\/www.cisilino.com\\\/en\\\/author\\\/matteocisilino\\\/#author\"},\"image\":{\"@type\":\"ImageObject\",\"url\":\"https:\\\/\\\/www.cisilino.com\\\/wp-content\\\/uploads\\\/2026\\\/10\\\/mysql-5-7-docker-nftables-firewall.webp\",\"@id\":\"https:\\\/\\\/www.cisilino.com\\\/en\\\/2026\\\/10\\\/17\\\/mysql-5-7-docker-nftables-firewall\\\/#mainImage\",\"width\":1200,\"height\":630,\"caption\":\"MySQL 5.7 in Docker: a database inside a box, surrounded by an orange dashed border, with a circle and a bar in front\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/www.cisilino.com\\\/en\\\/2026\\\/10\\\/17\\\/mysql-5-7-docker-nftables-firewall\\\/#mainImage\"},\"datePublished\":\"2026-10-17T10:10:45+02:00\",\"dateModified\":\"2026-10-29T20:00:39+01:00\"},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/www.cisilino.com\\\/en\\\/#website\",\"url\":\"https:\\\/\\\/www.cisilino.com\\\/en\\\/\",\"name\":\"Matteo Cisilino\",\"description\":\"Guide su WordPress, server e sicurezza\",\"inLanguage\":\"en-GB\",\"publisher\":{\"@id\":\"https:\\\/\\\/www.cisilino.com\\\/en\\\/#organization\"}}]}\n\t\t<\/script>\n\t\t<!-- All in One SEO -->\n\n","aioseo_head_json":{"title":"MySQL 5.7 in Docker protected with nftables","description":"How to run MySQL 5.7 in Docker on a modern server without exposing it to the internet: docker-compose, a closed port and an nftables firewall.","canonical_url":"https:\/\/www.cisilino.com\/en\/2026\/10\/17\/mysql-5-7-docker-nftables-firewall\/","robots":"max-image-preview:large","keywords":"","webmasterTools":{"google-site-verification":"_A-1f0dO30IDVHfP9muflI8kHQs-H4YOi8WLUkYzuLE","miscellaneous":""},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"BlogPosting","@id":"https:\/\/www.cisilino.com\/en\/2026\/10\/17\/mysql-5-7-docker-nftables-firewall\/#blogposting","name":"MySQL 5.7 in Docker protected with nftables","headline":"MySQL 5.7 in Docker protected with nftables","author":{"@id":"https:\/\/www.cisilino.com\/en\/author\/matteocisilino\/#author"},"publisher":{"@id":"https:\/\/www.cisilino.com\/en\/#organization"},"image":{"@type":"ImageObject","url":"https:\/\/www.cisilino.com\/wp-content\/uploads\/2026\/10\/mysql-5-7-docker-nftables-firewall.webp","width":1200,"height":630,"caption":"MySQL 5.7 in Docker: a database inside a box, surrounded by an orange dashed border, with a circle and a bar in front"},"datePublished":"2026-10-17T10:10:45+02:00","dateModified":"2026-10-29T20:00:39+01:00","inLanguage":"en-GB","mainEntityOfPage":{"@id":"https:\/\/www.cisilino.com\/en\/2026\/10\/17\/mysql-5-7-docker-nftables-firewall\/#webpage"},"isPartOf":{"@id":"https:\/\/www.cisilino.com\/en\/2026\/10\/17\/mysql-5-7-docker-nftables-firewall\/#webpage"},"articleSection":"Servers and databases, Docker, firewall, MySQL, nftables"},{"@type":"BreadcrumbList","@id":"https:\/\/www.cisilino.com\/en\/2026\/10\/17\/mysql-5-7-docker-nftables-firewall\/#breadcrumblist","itemListElement":[{"@type":"ListItem","@id":"https:\/\/www.cisilino.com\/en\/#listItem","position":1,"name":"Home","item":"https:\/\/www.cisilino.com\/en\/","nextItem":{"@type":"ListItem","@id":"https:\/\/www.cisilino.com\/en\/category\/servers-databases\/#listItem","name":"Servers and databases"}},{"@type":"ListItem","@id":"https:\/\/www.cisilino.com\/en\/category\/servers-databases\/#listItem","position":2,"name":"Servers and databases","item":"https:\/\/www.cisilino.com\/en\/category\/servers-databases\/","nextItem":{"@type":"ListItem","@id":"https:\/\/www.cisilino.com\/en\/2026\/10\/17\/mysql-5-7-docker-nftables-firewall\/#listItem","name":"MySQL 5.7 in Docker protected with nftables"},"previousItem":{"@type":"ListItem","@id":"https:\/\/www.cisilino.com\/en\/#listItem","name":"Home"}},{"@type":"ListItem","@id":"https:\/\/www.cisilino.com\/en\/2026\/10\/17\/mysql-5-7-docker-nftables-firewall\/#listItem","position":3,"name":"MySQL 5.7 in Docker protected with nftables","previousItem":{"@type":"ListItem","@id":"https:\/\/www.cisilino.com\/en\/category\/servers-databases\/#listItem","name":"Servers and databases"}}]},{"@type":"Organization","@id":"https:\/\/www.cisilino.com\/en\/#organization","name":"Matteo Cisilino","description":"Guide su WordPress, server e sicurezza","url":"https:\/\/www.cisilino.com\/en\/","logo":{"@type":"ImageObject","url":"https:\/\/www.cisilino.com\/wp-content\/uploads\/2026\/10\/logo-cisilino-512.png","@id":"https:\/\/www.cisilino.com\/en\/2026\/10\/17\/mysql-5-7-docker-nftables-firewall\/#organizationLogo","width":512,"height":512,"caption":"Logo: un cerchio a sinistra che si divide in cerchi pi\u00f9 piccoli"},"image":{"@id":"https:\/\/www.cisilino.com\/en\/2026\/10\/17\/mysql-5-7-docker-nftables-firewall\/#organizationLogo"}},{"@type":"Person","@id":"https:\/\/www.cisilino.com\/en\/author\/matteocisilino\/#author","url":"https:\/\/www.cisilino.com\/en\/author\/matteocisilino\/","name":"matteocisilino","image":{"@type":"ImageObject","@id":"https:\/\/www.cisilino.com\/en\/2026\/10\/17\/mysql-5-7-docker-nftables-firewall\/#authorImage","url":"https:\/\/secure.gravatar.com\/avatar\/639872265f0661e8aee8924ba9d756b00ea816f8286fab99a5116c729d49618f?s=96&d=mm&r=g","width":96,"height":96,"caption":"matteocisilino"}},{"@type":"WebPage","@id":"https:\/\/www.cisilino.com\/en\/2026\/10\/17\/mysql-5-7-docker-nftables-firewall\/#webpage","url":"https:\/\/www.cisilino.com\/en\/2026\/10\/17\/mysql-5-7-docker-nftables-firewall\/","name":"MySQL 5.7 in Docker protected with nftables","description":"How to run MySQL 5.7 in Docker on a modern server without exposing it to the internet: docker-compose, a closed port and an nftables firewall.","inLanguage":"en-GB","isPartOf":{"@id":"https:\/\/www.cisilino.com\/en\/#website"},"breadcrumb":{"@id":"https:\/\/www.cisilino.com\/en\/2026\/10\/17\/mysql-5-7-docker-nftables-firewall\/#breadcrumblist"},"author":{"@id":"https:\/\/www.cisilino.com\/en\/author\/matteocisilino\/#author"},"creator":{"@id":"https:\/\/www.cisilino.com\/en\/author\/matteocisilino\/#author"},"image":{"@type":"ImageObject","url":"https:\/\/www.cisilino.com\/wp-content\/uploads\/2026\/10\/mysql-5-7-docker-nftables-firewall.webp","@id":"https:\/\/www.cisilino.com\/en\/2026\/10\/17\/mysql-5-7-docker-nftables-firewall\/#mainImage","width":1200,"height":630,"caption":"MySQL 5.7 in Docker: a database inside a box, surrounded by an orange dashed border, with a circle and a bar in front"},"primaryImageOfPage":{"@id":"https:\/\/www.cisilino.com\/en\/2026\/10\/17\/mysql-5-7-docker-nftables-firewall\/#mainImage"},"datePublished":"2026-10-17T10:10:45+02:00","dateModified":"2026-10-29T20:00:39+01:00"},{"@type":"WebSite","@id":"https:\/\/www.cisilino.com\/en\/#website","url":"https:\/\/www.cisilino.com\/en\/","name":"Matteo Cisilino","description":"Guide su WordPress, server e sicurezza","inLanguage":"en-GB","publisher":{"@id":"https:\/\/www.cisilino.com\/en\/#organization"}}]},"og:locale":"en_GB","og:site_name":"Matteo Cisilino - Guide su WordPress, server e sicurezza","og:type":"article","og:title":"MySQL 5.7 in Docker protected with nftables","og:description":"How to run MySQL 5.7 in Docker on a modern server without exposing it to the internet: docker-compose, a closed port and an nftables firewall.","og:url":"https:\/\/www.cisilino.com\/en\/2026\/10\/17\/mysql-5-7-docker-nftables-firewall\/","og:image":"https:\/\/www.cisilino.com\/wp-content\/uploads\/2026\/10\/mysql-5-7-docker-nftables-firewall.webp","og:image:secure_url":"https:\/\/www.cisilino.com\/wp-content\/uploads\/2026\/10\/mysql-5-7-docker-nftables-firewall.webp","og:image:width":1200,"og:image:height":630,"article:published_time":"2026-10-17T08:10:45+00:00","article:modified_time":"2026-10-29T19:00:39+00:00","twitter:card":"summary_large_image","twitter:title":"MySQL 5.7 in Docker protected with nftables","twitter:description":"How to run MySQL 5.7 in Docker on a modern server without exposing it to the internet: docker-compose, a closed port and an nftables firewall.","twitter:image":"https:\/\/www.cisilino.com\/wp-content\/uploads\/2026\/10\/mysql-5-7-docker-nftables-firewall.webp"},"aioseo_meta_data":{"post_id":"271","title":"MySQL 5.7 in Docker protected with nftables","description":"How to run MySQL 5.7 in Docker on a modern server without exposing it to the internet: docker-compose, a closed port and an nftables firewall.","keywords":null,"keyphrases":{"focus":{"keyphrase":"mysql 5.7 in docker"}},"primary_term":null,"canonical_url":null,"og_title":null,"og_description":null,"og_object_type":"default","og_image_type":"default","og_image_custom_url":null,"og_image_custom_fields":null,"og_image_url":null,"og_image_width":null,"og_image_height":null,"og_video":null,"og_custom_url":null,"og_article_section":null,"og_article_tags":null,"twitter_use_og":false,"twitter_card":"default","twitter_image_type":"default","twitter_image_custom_url":null,"twitter_image_custom_fields":null,"twitter_image_url":null,"twitter_title":null,"twitter_description":null,"schema_type":"default","schema_type_options":null,"schema":{"blockGraphs":[],"customGraphs":[],"default":{"data":{"Article":[],"Course":[],"Dataset":[],"FAQPage":[],"Movie":[],"Person":[],"Product":[],"ProductReview":[],"Car":[],"Recipe":[],"Service":[],"SoftwareApplication":[],"WebPage":[]},"graphName":"","isEnabled":true},"graphs":[]},"pillar_content":false,"robots_default":true,"robots_noindex":false,"robots_noarchive":false,"robots_nosnippet":false,"robots_nofollow":false,"robots_noimageindex":false,"robots_noodp":false,"robots_notranslate":false,"robots_max_snippet":null,"robots_max_videopreview":null,"robots_max_imagepreview":"large","priority":null,"frequency":null,"local_seo":null,"limit_modified_date":false,"ai":null,"breadcrumb_settings":null,"seo_analyzer_scan_date":null,"created":"2026-10-29 09:24:03","updated":"2026-10-29 21:59:55","focus_keyword":"mysql 5.7 docker","additional_keywords":null,"truseo_locale":null},"aioseo_breadcrumb":"<div class=\"aioseo-breadcrumbs\"><span class=\"aioseo-breadcrumb\">\n\t\t\t<a href=\"https:\/\/www.cisilino.com\/en\/\" title=\"Home\">Home<\/a>\n\t\t<\/span><span class=\"aioseo-breadcrumb-separator\">\u00bb<\/span><span class=\"aioseo-breadcrumb\">\n\t\t\t<a href=\"https:\/\/www.cisilino.com\/en\/category\/servers-databases\/\" title=\"Servers and databases\">Servers and databases<\/a>\n\t\t<\/span><span class=\"aioseo-breadcrumb-separator\">\u00bb<\/span><span class=\"aioseo-breadcrumb\">\n\t\t\tMySQL 5.7 in Docker protected with nftables\n\t\t<\/span><\/div>","aioseo_breadcrumb_json":[{"label":"Home","link":"https:\/\/www.cisilino.com\/en\/"},{"label":"Servers and databases","link":"https:\/\/www.cisilino.com\/en\/category\/servers-databases\/"},{"label":"MySQL 5.7 in Docker protected with nftables","link":"https:\/\/www.cisilino.com\/en\/2026\/10\/17\/mysql-5-7-docker-nftables-firewall\/"}],"_links":{"self":[{"href":"https:\/\/www.cisilino.com\/en\/wp-json\/wp\/v2\/posts\/271","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.cisilino.com\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.cisilino.com\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.cisilino.com\/en\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.cisilino.com\/en\/wp-json\/wp\/v2\/comments?post=271"}],"version-history":[{"count":2,"href":"https:\/\/www.cisilino.com\/en\/wp-json\/wp\/v2\/posts\/271\/revisions"}],"predecessor-version":[{"id":899,"href":"https:\/\/www.cisilino.com\/en\/wp-json\/wp\/v2\/posts\/271\/revisions\/899"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.cisilino.com\/en\/wp-json\/wp\/v2\/media\/757"}],"wp:attachment":[{"href":"https:\/\/www.cisilino.com\/en\/wp-json\/wp\/v2\/media?parent=271"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.cisilino.com\/en\/wp-json\/wp\/v2\/categories?post=271"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.cisilino.com\/en\/wp-json\/wp\/v2\/tags?post=271"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}