diff --git a/docs/modules/nacos.md b/docs/modules/nacos.md
new file mode 100644
index 00000000000..e54c3509e86
--- /dev/null
+++ b/docs/modules/nacos.md
@@ -0,0 +1,35 @@
+# Hashicorp Nacos Module
+
+Testcontainers module for [Nacos](https://github.com/alibaba/nacos). Nacos an easy-to-use dynamic service discovery, configuration and service management platform for building AI cloud native applications. More information on Nacos [here](https://nacos.io/docs/latest/overview/).
+
+## Usage example
+
+
+[Running Nacos in your Junit tests](../../modules/nacos/src/test/java/org/testcontainers/nacos/NacosContainerTest.java)
+
+
+## Why Nacos in Junit tests?
+
+With the increasing popularity of Nacos and config externalization, applications are now needing to source properties from Nacos.
+This can prove challenging in the development phase without a running Nacos instance readily on hand. This library
+aims to solve your apps integration testing with Nacos. You can also use it to
+test how your application behaves with Nacos by writing different test scenarios in Junit.
+
+## Adding this module to your project dependencies
+
+Add the following dependency to your `pom.xml`/`build.gradle` file:
+
+=== "Gradle"
+ ```groovy
+ testImplementation "org.testcontainers:nacos:{{latest_version}}"
+ ```
+
+=== "Maven"
+ ```xml
+
+ org.testcontainers
+ nacos
+ {{latest_version}}
+ test
+
+ ```
diff --git a/modules/nacos/build.gradle b/modules/nacos/build.gradle
new file mode 100644
index 00000000000..5e20eb2d872
--- /dev/null
+++ b/modules/nacos/build.gradle
@@ -0,0 +1,16 @@
+description = "Testcontainers :: Nacos"
+
+dependencies {
+ api project(':testcontainers')
+
+ testRuntimeOnly 'org.junit.platform:junit-platform-launcher:1.11.0'
+
+ testImplementation 'org.junit.jupiter:junit-jupiter:5.13.4'
+ testImplementation 'com.alibaba.nacos:nacos-client:3.0.3'
+ testImplementation 'io.rest-assured:rest-assured:5.5.6'
+ testImplementation 'org.assertj:assertj-core:3.27.4'
+}
+
+test {
+ useJUnitPlatform()
+}
diff --git a/modules/nacos/src/main/java/org/testcontainers/nacos/NacosContainer.java b/modules/nacos/src/main/java/org/testcontainers/nacos/NacosContainer.java
new file mode 100644
index 00000000000..69fb6e51e6f
--- /dev/null
+++ b/modules/nacos/src/main/java/org/testcontainers/nacos/NacosContainer.java
@@ -0,0 +1,63 @@
+package org.testcontainers.nacos;
+
+import org.testcontainers.containers.GenericContainer;
+import org.testcontainers.containers.wait.strategy.Wait;
+import org.testcontainers.utility.DockerImageName;
+
+/**
+ * Testcontainers implementation for Nacos.
+ *
+ * Supported images: {@code nacos/nacos-server}, {@code nacos}
+ *
+ * Exposed ports:
+ *
+ * - HTTP: 8848
+ * - HTTP: 8080
+ * - gRPC: 9848
+ *
+ *
+ */
+public class NacosContainer extends GenericContainer {
+
+ private static final DockerImageName DEFAULT_OLD_IMAGE_NAME = DockerImageName.parse("nacos");
+
+ private static final DockerImageName DEFAULT_IMAGE_NAME = DockerImageName.parse("nacos/nacos-server");
+
+ private static final int NACOS_HTTP_ADMIN_PORT = 8848;
+
+ private static final int NACOS_HTTP_CONSOLE_PORT = 8080;
+
+ private static final int NACOS_GRPC_PORT = 9848;
+
+ public NacosContainer(String dockerImageName) {
+ this(DockerImageName.parse(dockerImageName), 38848, 38080, 39848);
+ }
+
+ public NacosContainer(final DockerImageName dockerImageName, int adminPort, int consolePort, int grpcPort) {
+ super(dockerImageName);
+ dockerImageName.assertCompatibleWith(DEFAULT_OLD_IMAGE_NAME, DEFAULT_IMAGE_NAME);
+
+ // Wait until the Nacos server is ready to accept requests.
+ // Visit the login page to verify if nacos is running.
+ setWaitStrategy(Wait.forHttp("/#/login").forPort(NACOS_HTTP_CONSOLE_PORT).forStatusCode(200));
+
+ // According to Nacos' design, the gRPC client port adds 1000 to the main port, which means that if the main port is 8849, the gRPC port defaults to 9849
+ addFixedExposedPort(adminPort, NACOS_HTTP_ADMIN_PORT);
+ addFixedExposedPort(consolePort, NACOS_HTTP_CONSOLE_PORT);
+ addFixedExposedPort(grpcPort, NACOS_GRPC_PORT);
+
+ // Configure Nacos for single machine startup.
+ withEnv("MODE", "standalone");
+ // Nacos is used to generate keys for JWT tokens, using strings longer than 32 characters and then encoded with Base64.
+ withEnv("NACOS_AUTH_TOKEN", "SecretKey012345678901234567890123456789012345678901234567890123456789");
+ // The key for the identity identifier of the Inner API between Nacos servers is required.
+ withEnv("NACOS_AUTH_IDENTITY_KEY", "serverIdentity");
+ // The value of the identity identifier for the Inner API between Nacos servers is required.
+ withEnv("NACOS_AUTH_IDENTITY_VALUE", "security");
+ }
+
+ public String getServerAddr() {
+ return String.format("%s:%s", this.getHost(), this.getMappedPort(NACOS_HTTP_ADMIN_PORT));
+ }
+
+}
diff --git a/modules/nacos/src/test/java/org/testcontainers/nacos/NacosContainerTest.java b/modules/nacos/src/test/java/org/testcontainers/nacos/NacosContainerTest.java
new file mode 100644
index 00000000000..1c79274ccf8
--- /dev/null
+++ b/modules/nacos/src/test/java/org/testcontainers/nacos/NacosContainerTest.java
@@ -0,0 +1,52 @@
+package org.testcontainers.nacos;
+
+import com.alibaba.nacos.api.NacosFactory;
+import com.alibaba.nacos.api.PropertyKeyConst;
+import com.alibaba.nacos.api.config.ConfigService;
+import com.alibaba.nacos.api.exception.NacosException;
+import org.junit.jupiter.api.AfterAll;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import java.util.Properties;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+class NacosContainerTest {
+
+ private ConfigService configService;
+
+ private static NacosContainer nacos = new NacosContainer("nacos/nacos-server:v3.0.3");
+
+ @BeforeAll
+ static void setup() {
+ nacos.start();
+ }
+
+ @AfterAll
+ static void teardown() {
+ nacos.stop();
+ }
+
+ @BeforeEach
+ void init() throws NacosException {
+ Properties properties = new Properties();
+ properties.put(PropertyKeyConst.SERVER_ADDR, nacos.getServerAddr());
+ properties.put(PropertyKeyConst.USERNAME, "nacos");
+ properties.put(PropertyKeyConst.PASSWORD, "nacos");
+ configService = NacosFactory.createConfigService(properties);
+ }
+
+
+ @Test
+ void writeAndRemoveValue() throws NacosException, InterruptedException {
+ assertThat(configService.publishConfig("test.yaml", "DEFAULT", "name: 123")).isTrue();
+ Thread.sleep(1500);
+ assertThat(configService.getConfig("test.yaml", "DEFAULT", 5000)).isEqualTo("name: 123");
+ assertThat(configService.removeConfig("test.yaml", "DEFAULT")).isTrue();
+ Thread.sleep(1500);
+ assertThat(configService.getConfig("test.yaml", "DEFAULT", 5000)).isEqualTo(null);
+ }
+
+}
diff --git a/modules/nacos/src/test/resources/logback-test.xml b/modules/nacos/src/test/resources/logback-test.xml
new file mode 100644
index 00000000000..83ef7a1a3ef
--- /dev/null
+++ b/modules/nacos/src/test/resources/logback-test.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+ %d{HH:mm:ss.SSS} %-5level %logger - %msg%n
+
+
+
+
+
+
+
+
+