bind dev Docker ports, socket REPL, and rspack dev server to loopback only (#82707)

This commit is contained in:
Aleksandr Lesnenko
2026-09-18 23:27:04 -04:00
committed by GitHub
parent 883e944cce
commit 3d924036db
22 changed files with 80 additions and 66 deletions

View File

@@ -121,6 +121,9 @@ MB_EDITION="ee"
# Frontend dev server port (for hot reload). Must match the port used by `yarn build-hot`.
# MB_FRONTEND_DEV_PORT=8080
# Frontend dev server bind address. Defaults to 127.0.0.1; set 0.0.0.0 to reach it from other devices.
# MB_FRONTEND_DEV_HOST=127.0.0.1
# 3.2 E2E Local Runner Setup
# ------------------------------------------------------------------------------

View File

@@ -27,7 +27,7 @@ services:
metabase:
image: ${METABASE_IMAGE:-metabase/metabase:latest}
ports:
- "${METABASE_PORT:-3000}:3000"
- "127.0.0.1:${METABASE_PORT:-3000}:3000"
environment:
MB_DB_TYPE: postgres
MB_DB_DBNAME: metabase

View File

@@ -941,8 +941,10 @@
{:extra-deps {nrepl/nrepl {:mvn/version "1.5.1"}}
:main-opts ["-m" "nrepl.cmdline" "-p" "50605"]}
;; - start a Socket REPL on port 50505 that you can connect your editor to:
:socket {:jvm-opts ["-Dclojure.server.repl={:address,\"0.0.0.0\",:port,50505,:accept,clojure.core.server/repl}"]}
;; - start a Socket REPL on port 50505 that you can connect your editor to. Bound to loopback: it has no
;; authentication, so exposing it on a network interface is remote code execution. dev/docker-compose.yml
;; overrides the address for the containerized dev app, where the published port is the boundary.
:socket {:jvm-opts ["-Dclojure.server.repl={:address,\"127.0.0.1\",:port,50505,:accept,clojure.core.server/repl}"]}
;; Liquibase CLI:
;;

View File

@@ -39,8 +39,8 @@ services:
image: clojure
container_name: metabase-app
ports:
- "3001:3000"
- "50505:50505"
- "127.0.0.1:3001:3000"
- "127.0.0.1:50505:50505"
working_dir: /dev/metabase
volumes:
- ../:/dev/metabase
@@ -58,7 +58,10 @@ services:
MB_POSTGRESQL_TEST_PASSWORD: password
MB_POSTGRESQL_TEST_PORT: 5432
MB_POSTGRESQL_TEST_USER: user
command: ["clojure", "-M:run:dev:drivers:drivers-dev:ee:ee-dev:socket"]
# The :socket alias binds the REPL to loopback inside the container, which docker's port
# forwarding can't reach, so bind it to all container interfaces here instead. The host
# side stays loopback-only via the 127.0.0.1: prefix in `ports` above.
command: ["clojure", "-J-Dclojure.server.repl={:address,\"0.0.0.0\",:port,50505,:accept,clojure.core.server/repl}", "-M:run:dev:drivers:drivers-dev:ee:ee-dev"]
profiles:
- dev-app
networks:
@@ -79,10 +82,14 @@ services:
# the browser loads the bundle from the host's :8080 — it must be
# published, not just exposed on the docker network.
ports:
- "8080:8080"
- "127.0.0.1:8080:8080"
volumes:
- ../:/dev/metabase
- ~/.bun/install/cache:/root/.bun/install/cache
environment:
# rspack binds to loopback by default; inside the container it must listen on all
# interfaces for docker's port forwarding to reach it.
MB_FRONTEND_DEV_HOST: 0.0.0.0
command:
- /bin/sh
- -c
@@ -99,7 +106,7 @@ services:
container_name: metabase-postgres-app-db
restart: always
ports:
- "5432:5432"
- "127.0.0.1:5432:5432"
environment:
POSTGRES_USER: mbuser
POSTGRES_PASSWORD: password
@@ -116,7 +123,7 @@ services:
container_name: metabase-mysql57-app-db
restart: always
ports:
- "3306:3306"
- "127.0.0.1:3306:3306"
environment:
MYSQL_USER: mbuser
MYSQL_PASSWORD: password
@@ -138,7 +145,7 @@ services:
image: metabase/qa-databases:postgres-sample-14
container_name: metabasedb_postgres_14_data
ports:
- "15432:5432"
- "127.0.0.1:15432:5432"
restart: always
profiles:
- postgres14data
@@ -149,7 +156,7 @@ services:
image: metabase/qa-databases:mysql-sample-5.7
container_name: metabasedb_mysql_5_7_data
ports:
- "23306:3306"
- "127.0.0.1:23306:3306"
restart: always
profiles:
- mysql57data
@@ -160,7 +167,7 @@ services:
image: metabase/qa-databases:mysql-sample-8
container_name: metabasedb_mysql_8_data
ports:
- "13306:3306"
- "127.0.0.1:13306:3306"
restart: always
profiles:
- mysql8data
@@ -172,7 +179,7 @@ services:
container_name: metabasedb_mongo_6_data
restart: always
ports:
- "27017:27017"
- "127.0.0.1:27017:27017"
profiles:
- mongodata
networks:
@@ -183,7 +190,7 @@ services:
container_name: vertica_data
restart: always
ports:
- "5433:5433"
- "127.0.0.1:5433:5433"
profiles:
- verticadata
networks:
@@ -195,8 +202,8 @@ services:
image: maildev/maildev:latest
container_name: maildev
ports:
- "1080:1080"
- "1025:1025"
- "127.0.0.1:1080:1080"
- "127.0.0.1:1025:1025"
profiles:
- pulse
networks:
@@ -209,7 +216,7 @@ services:
- ./idp-private-key.pem:/idp-private-key.pem
- ./idp-public-cert.pem:/idp-public-cert.pem
ports:
- "7000:7000"
- "127.0.0.1:7000:7000"
entrypoint:
- node
- app.js

View File

@@ -33,7 +33,7 @@ Once Docker is installed, you’re ready to go.
2. Copy and paste this command, switching out `<branch-name>` for the name of the branch you’d like to test:
```bash
docker run --platform linux/amd64 -d -p 3000:3000 --name metabase-dev metabase/metabase-dev:<branch-name>
docker run --platform linux/amd64 -d -p 127.0.0.1:3000:3000 --name metabase-dev metabase/metabase-dev:<branch-name>
```
3. In your browser, navigate to `http://localhost:3000`, where you should see Metabase. It may take a minute or two to start up depending on your computer.
@@ -51,7 +51,7 @@ docker pull metabase/metabase-enterprise-head:latest
Then:
```
docker run --platform linux/amd64 -d -p 3000:3000 --name metabase metabase/metabase-enterprise-head:latest
docker run --platform linux/amd64 -d -p 127.0.0.1:3000:3000 --name metabase metabase/metabase-enterprise-head:latest
```
The “latest” tag is not automatically upgraded on your local machine, so the above commands ensure that you’re pulling the latest changes.

View File

@@ -171,7 +171,7 @@ We have a few helpers for dealing with tests involving snowplow
Some of our tests depend on the email being set up, and require a local SMTP server. We use `maildev` Docker image for that purpose. At the time of this writing the image we use is `maildev/maildev:2.1.0`. The default cypress configuration for local development will handle this for you. If you want to set it up manually, you can use this command:
```sh
docker run -d -p 1180:1080 -p 1125:1025 maildev/maildev:2.2.1
docker run -d -p 127.0.0.1:1180:1080 -p 127.0.0.1:1125:1025 maildev/maildev:2.2.1
```
The e2e maildev is published on host ports 1180 (web UI) and 1125 (SMTP) on purpose. These differ, on purpose, from the 1080/1025 used for development.

View File

@@ -13,7 +13,7 @@ const { WEB_PORT, SMTP_PORT } = WEBMAIL_CONFIG;
/**
* `bun run test-cypress` starts maildev for you via
* e2e/test/scenarios/docker-compose.yml. To start it manually instead:
* `docker run -d -p 1180:1080 -p 1125:1025 maildev/maildev:2.2.1`
* `docker run -d -p 127.0.0.1:1180:1080 -p 127.0.0.1:1125:1025 maildev/maildev:2.2.1`
* or
* `npx maildev -s 1125 -w 1180`
*/

View File

@@ -1,6 +1,6 @@
/**
Make sure you have the ldap test server running locally:
docker run -p 389:389 \
docker run -p 127.0.0.1:389:389 \
--env LDAP_ADMIN_PASSWORD=adminpass \
--env LDAP_USERS=user01@example.org,user02@example.org \
--env LDAP_PASSWORDS=123456,123465 \

View File

@@ -883,7 +883,7 @@ describe("scenarios > admin > settings > map settings", () => {
});
// Ensure the webhook tester docker container is running
// docker run -p 9080:8080/tcp tarampampam/webhook-tester:1.1.0 serve --create-session 00000000-0000-0000-0000-000000000000
// docker run -p 127.0.0.1:9080:8080/tcp tarampampam/webhook-tester:1.1.0 serve --create-session 00000000-0000-0000-0000-000000000000
describe("notifications", { tags: "@external" }, () => {
beforeEach(() => {
H.resetWebhookTester();

View File

@@ -9,32 +9,32 @@ services:
- TZ=US/Pacific
image: metabase/qa-databases:postgres-sample-12
ports:
- 5404:5432
- 127.0.0.1:5404:5432
mongo-sample:
image: metabase/qa-databases:mongo-sample-5
ports:
- 27004:27017
- 127.0.0.1:27004:27017
mysql-sample:
environment:
- TZ=US/Pacific
image: metabase/qa-databases:mysql-sample-8
ports:
- 3304:3306
- 127.0.0.1:3304:3306
webhook-tester:
image: tarampampam/webhook-tester:1.1.0
ports:
- 9080:8080
- 127.0.0.1:9080:8080
command: serve --create-session 00000000-0000-0000-0000-000000000000
maildev:
image: maildev/maildev:2.2.1
## Host ports deliberately differ from the 1080/1025 used for development
ports:
- "1180:1080"
- "1125:1025"
- "127.0.0.1:1180:1080"
- "127.0.0.1:1125:1025"
maildev-ssl:
## NOTE: Using this requires a root CA certificate to be added to the Java keystore.
@@ -43,8 +43,8 @@ services:
## breaks the SSL/SMTP setup and fails the custom SMTP e2e tests.
image: maildev/maildev:2.2.1
ports:
- "1081:1081"
- "465:465"
- "127.0.0.1:1081:1081"
- "127.0.0.1:465:465"
environment:
NODE_TLS_REJECT_UNAUTHORIZED: 0
MAILDEV_WEB_PORT: 1081
@@ -58,7 +58,7 @@ services:
saml-idp:
image: boxyhq/mock-saml:1.4.2
ports:
- "8090:4000"
- "127.0.0.1:8090:4000"
environment:
APP_URL: http://localhost:8090
ENTITY_ID: https://saml.example.com/entityid
@@ -68,7 +68,7 @@ services:
ldap:
image: bitnamilegacy/openldap:2.6.4
ports:
- "389:389"
- "127.0.0.1:389:389"
environment:
LDAP_ADMIN_PASSWORD: adminpass
LDAP_USERS: user01@example.org,user02@example.org

View File

@@ -592,7 +592,7 @@ describe("scenarios > question > saved", () => {
//http://127.0.0.1:9080/api/session/00000000-0000-0000-0000-000000000000/requests
// Ensure the webhook tester docker container is running
// docker run -p 9080:8080/tcp tarampampam/webhook-tester:1.1.0 serve --create-session 00000000-0000-0000-0000-000000000000
// docker run -p 127.0.0.1:9080:8080/tcp tarampampam/webhook-tester:1.1.0 serve --create-session 00000000-0000-0000-0000-000000000000
describe(
"scenarios > question > saved > alerts",
{ tags: ["@external"] },

View File

@@ -13,7 +13,7 @@ services:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
ports:
- "55432:5432"
- "127.0.0.1:55432:5432"
volumes:
- pgvector17_data:/var/lib/postgresql/data
healthcheck:
@@ -25,7 +25,7 @@ services:
ollama:
image: ollama/ollama:latest
ports:
- "11434:11434"
- "127.0.0.1:11434:11434"
volumes:
- ollama_data:/root/.ollama
healthcheck:

View File

@@ -104,7 +104,7 @@ export const startLocalMetabaseContainer: CliStepMethod = async (state) => {
.join(" ");
const { stderr, stdout } = await exec(
`docker run --pull always --detach -p ${port}:3000 ${envFlags} --name ${CONTAINER_NAME} ${IMAGE_NAME}`,
`docker run --pull always --detach -p 127.0.0.1:${port}:3000 ${envFlags} --name ${CONTAINER_NAME} ${IMAGE_NAME}`,
);
if (stdout) {

View File

@@ -227,7 +227,7 @@
container-name (str container-prefix "-" suffix)
host-port (host-port-for-image image ci-port-mapping)
container-port (second (str/split ci-port-mapping #":"))
port-mapping (str host-port ":" container-port)
port-mapping (str "127.0.0.1:" host-port ":" container-port)
current-image (running-container-image container-name)]
(if (= current-image image)
(do (println (c/green "Reusing existing") container-name (str "(" image ")"))
@@ -378,7 +378,7 @@
container-name (str container-prefix "-" suffix)
host-port (host-port-for-image image ci-ports)
container-port (second (str/split ci-ports #":"))
port-mapping (str host-port ":" container-port)
port-mapping (str "127.0.0.1:" host-port ":" container-port)
env-args (mapcat (fn [[k v]] ["-e" (str (name k) "=" v)]) (or svc-env {}))]]
(vec (concat ["docker" "run" "-d"
"--name" container-name
@@ -441,7 +441,6 @@
(println)
(println (c/bold (str "=== CI Test REPL: " (display-name test-job) " ===")))
(println)
;; Start Docker services and collect port remappings
(let [port-remaps (if (has-services? test-job)
(start-services! test-job)
@@ -451,7 +450,6 @@
(println (c/bold "Starting nREPL") "(aliases: :dev:ee:ee-dev:drivers:drivers-dev)...")
(println "To stop containers:" (c/green (str "docker rm -f $(docker ps -q --filter name=" container-prefix ")")))
(println)
;; Replace this process with the nREPL (like shell `exec`)
(let [extra-env (into {} (map (fn [[k v]] [(name k) (str v)]) ci-env))]
(process/exec {:extra-env extra-env}

View File

@@ -135,7 +135,7 @@
(into ["docker" "run" "-d"]
(concat
(mapcat (fn [[host-port internal-port]]
["-p" (str host-port ":" internal-port)])
["-p" (str "127.0.0.1:" host-port ":" internal-port)])
port-mappings)
(mapcat (fn [[k v]]
["-e" (str k "=" v)])

View File

@@ -115,7 +115,7 @@
(into ["docker" "run" "-d"]
(concat
(mapcat (fn [[host-port internal-port]]
["-p" (str host-port ":" internal-port)])
["-p" (str "127.0.0.1:" host-port ":" internal-port)])
port-mappings)
(mapcat (fn [[k v]]
["-e" (str k "=" v)])

View File

@@ -126,7 +126,7 @@
(into ["docker" "run" "-d"]
(concat
(mapcat (fn [[host-port internal-port]]
["-p" (str host-port ":" internal-port)])
["-p" (str "127.0.0.1:" host-port ":" internal-port)])
port-mappings)
(mapcat (fn [[k v]]
["-e" (str k "=" v)])

View File

@@ -92,7 +92,7 @@
(defmethod docker-cmd :postgres
[_db container-name resolved-version port]
["docker" "run" "-d"
"-p" (str port ":5432")
"-p" (str "127.0.0.1:" port ":5432")
;; "--network" "psql-metabase-network"
"-e" "POSTGRES_USER=metabase"
"-e" "POSTGRES_DB=metabase"
@@ -105,7 +105,7 @@
(defmethod docker-cmd :mysql
[_db container-name resolved-version port]
["docker" "run" "-d"
"-p" (str port ":3306")
"-p" (str "127.0.0.1:" port ":3306")
"-e" "MYSQL_DATABASE=metabase_test"
"-e" "MYSQL_ALLOW_EMPTY_PASSWORD=yes"
"--name" container-name
@@ -114,7 +114,7 @@
(defmethod docker-cmd :mariadb
[_db container-name resolved-version port]
["docker" "run" "-d"
"-p" (str port ":3306")
"-p" (str "127.0.0.1:" port ":3306")
"-e" "MYSQL_DATABASE=metabase_test"
"-e" "MYSQL_ALLOW_EMPTY_PASSWORD=yes"
"--name" container-name
@@ -125,7 +125,7 @@
["docker" "run" "-d"
"-e" "MONGO_INITDB_ROOT_USERNAME=metabase"
"-e" "MONGO_INITDB_ROOT_PASSWORD=metasample123"
"-p" (str port ":27017")
"-p" (str "127.0.0.1:" port ":27017")
"--name" container-name
(str "mongo:" resolved-version)])
@@ -141,7 +141,7 @@
(defmethod docker-cmd :sqlserver
[_db container-name resolved-version port]
["docker" "run" "-d"
"-p" (str port ":1433")
"-p" (str "127.0.0.1:" port ":1433")
"-e" "ACCEPT_EULA=Y"
"-e" "SA_PASSWORD=P@ssw0rd"
"--name" container-name
@@ -150,7 +150,7 @@
(defmethod docker-cmd :oracle
[_db container-name resolved-version port]
["docker" "run" "-d"
"-p" (str port ":1521")
"-p" (str "127.0.0.1:" port ":1521")
"-e" "ORACLE_PASSWORD=password"
"--name" container-name
(if (= resolved-version "latest")

View File

@@ -9,8 +9,8 @@ services:
container_name: 'mb-clickhouse-latest'
hostname: clickhouse
ports:
- '8123:8123'
- '9000:9000'
- '127.0.0.1:8123:8123'
- '127.0.0.1:9000:9000'
environment:
CLICKHOUSE_SKIP_USER_SETUP: 1
ulimits:
@@ -32,8 +32,8 @@ services:
dockerfile: .docker/clickhouse/single_node_tls/Dockerfile
container_name: 'metabase-driver-clickhouse-server-tls'
ports:
- '8443:8443'
- '9440:9440'
- '127.0.0.1:8443:8443'
- '127.0.0.1:9440:9440'
environment:
CLICKHOUSE_SKIP_USER_SETUP: 1
ulimits:
@@ -56,8 +56,8 @@ services:
container_name: 'mb-clickhouse-oldest'
hostname: clickhouse.older
ports:
- '8124:8123'
- '9001:9000'
- '127.0.0.1:8124:8123'
- '127.0.0.1:9001:9000'
environment:
CLICKHOUSE_SKIP_USER_SETUP: 1
ulimits:
@@ -82,9 +82,9 @@ services:
hostname: clickhouse1
container_name: metabase-driver-clickhouse-cluster-node-1
ports:
- '8125:8123'
- '9002:9000'
- '9181:9181'
- '127.0.0.1:8125:8123'
- '127.0.0.1:9002:9000'
- '127.0.0.1:9181:9181'
environment:
CLICKHOUSE_SKIP_USER_SETUP: 1
volumes:
@@ -101,9 +101,9 @@ services:
hostname: clickhouse2
container_name: metabase-driver-clickhouse-cluster-node-2
ports:
- '8126:8123'
- '9003:9000'
- '9182:9181'
- '127.0.0.1:8126:8123'
- '127.0.0.1:9003:9000'
- '127.0.0.1:9182:9181'
environment:
CLICKHOUSE_SKIP_USER_SETUP: 1
volumes:
@@ -117,7 +117,7 @@ services:
image: 'nginx:1.23.1-alpine'
hostname: nginx
ports:
- '8127:8123'
- '127.0.0.1:8127:8123'
volumes:
- './.docker/nginx/local.conf:/etc/nginx/conf.d/local.conf'
container_name: metabase-nginx

View File

@@ -49,6 +49,10 @@ const isEEBuild = process.env.MB_EDITION === "ee";
const SDK_DOCS_SNIPPETS_PATH = __dirname + "/docs/embedding/sdk/snippets";
const PORT = process.env.MB_FRONTEND_DEV_PORT || 8080;
// Bind to loopback by default so the hot-reload server is not reachable from the
// local network. Set MB_FRONTEND_DEV_HOST=0.0.0.0 to serve it to other devices
// (or from inside a container, where the published port is the boundary).
const HOST = process.env.MB_FRONTEND_DEV_HOST || "127.0.0.1";
const isDevMode = IS_DEV_MODE;
const shouldEnableHotRefresh = WEBPACK_BUNDLE === "hot";
@@ -465,7 +469,7 @@ if (shouldEnableHotRefresh) {
// if you want to reduce stats noise
// stats: 'minimal' // values: none, errors-only, minimal, normal, verbose
},
host: "0.0.0.0",
host: HOST,
};
config.watchOptions = {

View File

@@ -2,7 +2,7 @@ services:
snowplow-micro:
image: snowplow/snowplow-micro:2.3.0
ports:
- "9090:9090"
- "127.0.0.1:9090:9090"
volumes:
- .:/config
command: "--collector-config /config/micro.conf --iglu /config/iglu.json"

View File

@@ -33,7 +33,7 @@ fi
echo "Running mongod version ${version} in SSL mode ${ssl}"
docker run -d -it --rm -p 27017:27017 --name metamongo \
docker run -d -it --rm -p 127.0.0.1:27017:27017 --name metamongo \
-e MONGO_INITDB_ROOT_USERNAME=metabase \
-e MONGO_INITDB_ROOT_PASSWORD=metasample123 \
metabase/qa-databases:mongo-sample-${version} \