{"id":21251887,"url":"https://github.com/nawodyaishan/multiple-docker-example","last_synced_at":"2026-04-08T23:33:17.299Z","repository":{"id":207818921,"uuid":"716245124","full_name":"nawodyaishan/multiple-docker-example","owner":"nawodyaishan","description":"This project is a Dockerized Node.js application that uses Redis for managing visit counts. It demonstrates the integration of Node.js with Redis within a Docker environment, showcasing best practices in containerization and application design.","archived":false,"fork":false,"pushed_at":"2023-11-18T04:04:06.000Z","size":47,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-07-22T23:54:54.691Z","etag":null,"topics":["docker","docker-compose","docker-image","express","node-js","redis","typescript"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/nawodyaishan.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-11-08T18:26:55.000Z","updated_at":"2023-11-17T17:49:31.000Z","dependencies_parsed_at":"2025-01-21T20:49:17.474Z","dependency_job_id":"4588a37e-8819-4894-abe9-274b7d405f4a","html_url":"https://github.com/nawodyaishan/multiple-docker-example","commit_stats":null,"previous_names":["nawodyaishan/multiple-docker-example"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/nawodyaishan/multiple-docker-example","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nawodyaishan%2Fmultiple-docker-example","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nawodyaishan%2Fmultiple-docker-example/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nawodyaishan%2Fmultiple-docker-example/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nawodyaishan%2Fmultiple-docker-example/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/nawodyaishan","download_url":"https://codeload.github.com/nawodyaishan/multiple-docker-example/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nawodyaishan%2Fmultiple-docker-example/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31579054,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-08T14:31:17.711Z","status":"ssl_error","status_checked_at":"2026-04-08T14:31:17.202Z","response_time":54,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["docker","docker-compose","docker-image","express","node-js","redis","typescript"],"created_at":"2024-11-21T03:45:22.682Z","updated_at":"2026-04-08T23:33:17.283Z","avatar_url":"https://github.com/nawodyaishan.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Project Overview\n\nThis project is a Dockerized Node.js application that uses Redis for managing visit counts. It demonstrates the integration of Node.js with Redis within a Docker environment, showcasing best practices in containerization and application design.\n\n### Key Features\n\n- **Node.js Backend:** A lightweight and efficient server using Express.js.\n- **Redis Integration:** Utilizes Redis as a database to store visit counts.\n- **Docker Support:** Containerized with Docker for easy deployment and scaling.\n- **TypeScript Support:** Leveraging TypeScript for improved code reliability and maintainability.\n\n# Getting Started\n\nThese instructions will get your copy of the project up and running on your local machine for development and testing purposes.\n\n### Prerequisites\n\n- [Docker](https://www.docker.com/get-started)\n- [Node.js](https://nodejs.org/en/) (for local development)\n\n### Installation\n\n1. **Clone the repository**\n\n    ```bash\n    git clone \u003chttps://github.com/nawodyaishan/docker-nodejs.git\u003e\n    cd docker-nodejs\n    ```\n\n2. **Build the Docker image**\n\n    ```bash\n    docker build -t docker-nodejs .\n    ```\n\n3. **Run the Docker container**\n\n    ```bash\n    docker run -p 3000:3000 docker-nodejs\n    ```\n\n   This will start the application and expose it on `http://localhost:3000`.\n\n\n## Application Structure\n\n- `Dockerfile`: Contains the Docker configuration for building the image.\n- `package.json`: Lists the project dependencies and scripts.\n- `pnpm-lock.yaml`: Lock file to ensure consistent installation of dependencies.\n- `src/index.ts`: The main server file written in TypeScript.\n- `tsconfig.json`: TypeScript compiler configuration.\n\n## Dockerfile Explained\n\n```yaml\n# Use a specific version of Node.js on Alpine Linux as the base image\nFROM node:18-alpine3.17\n\n# Set environment variables for PNPM's installation location and update PATH\nENV PNPM_HOME=\"/pnpm\"\nENV PATH=\"$PNPM_HOME:$PATH\"\n\n# Enable Corepack for managing package managers like pnpm\nRUN corepack enable\n\n# Set the working directory in the container\nWORKDIR '/app'\n\n# Copy package.json and pnpm-lock.yaml\nCOPY package.json pnpm-lock.yaml ./\n\n# Install project dependencies using pnpm\nRUN pnpm install\n\n# Copy the rest of the application's code\nCOPY . .\n\n# Command to run the application\nCMD [\"pnpm\",\"start\"]\n```\n\n# Running Redis Image\n\n### Prerequisites\n\n- Ensure you have [Docker installed](https://www.docker.com/products/docker-desktop) on your machine.\n\n### Steps to Run Redis Image\n\n1. **Pull the Redis Image**\n\n   First, you need to pull the official Redis image from Docker Hub. Open a terminal or command prompt and run the\n   following command:\n\n    ```bash\n    docker pull redis\n    ```\n\n   This command downloads the latest Redis image to your local machine.\n\n2. **Run the Redis Container**\n\n   After pulling the image, you can start a Redis container. Run the following command:\n\n    ```bash\n    docker run --name my-redis -p 6379:6379 -d redis\n    ```\n\n   Here’s what each part of this command does:\n\n    - `-name my-redis`: Assigns the name `my-redis` to your Docker container.\n    - `p 6379:6379`: Maps port 6379 of the container to port 6379 on your host machine. Redis by default runs on port\n      6379.\n    - `d`: Runs the container in detached mode, meaning the container runs in the background.\n    - `redis`: Specifies the Redis image to use.\n\n   After running this command, Redis will be up and running in a Docker container.\n\n3. **Verify Redis Container is Running**\n\n   You can check if your Redis container is running by executing:\n\n    ```bash\n    docker ps\n    ```\n\n   This will list all active containers. Look for the `my-redis` container in the list.\n\n4. **Stopping the Redis Container**\n\n   When you're done, you can stop the Redis container by running:\n\n    ```bash\n    docker stop my-redis\n    ```\n\n5. **Restarting the Redis Container**\n\n   To restart the container, use:\n\n    ```bash\n    docker start my-redis\n    ```\n\n# Setting Up Networking Infrastructure\n\n## Using Docker Compose\n\nThe `docker-compose.yml` defines a multi-container Docker application with two services: a Redis server and a Node.js\napplication. Below is a detailed explanation of the configuration file and how to use it.\n\n```yaml\nversion: '3' # Specifies the version of the Docker Compose file format\n\nservices: # Defines the services that make up your application\n\n  my-redis: # Name of the first service\n    image: 'redis' # Specifies the Redis image from Docker Hub\n\n  node-app: # Name of the second service\n    build: . # Builds an image using the Dockerfile in the current directory\n    ports:\n      - \"4001:4001\" # Maps port 4001 inside the container to port 4001 on the host\n```\n\n### Breakdown of Services\n\n1. **Redis Server:**\n    - The service `redis-server` uses the official `redis` image from Docker Hub.\n    - No ports are exposed to the host in this configuration, meaning Redis will only be accessible to other services\n      within the same Docker network (like your `node-app` service).\n2. **Node Application:**\n    - The `node-app` service is built using the `Dockerfile` in the current directory (specified by `build: .`).\n    - The application inside the container listening on port `8081` will be accessible on port `4001` of your host\n      machine.\n\n## Using the Docker Compose File\n\nTo use this `docker-compose.yml` file, follow these steps:\n\n### Steps to Run\n\n1. **Navigate to the Project Directory:**\n\n   Ensure you are in the directory where your `docker-compose.yml` file and the `Dockerfile` for your Node.js\n   application are located.\n\n2. **Running Docker Compose:**\n\n   Run the following command to build and start your services:\n\n    ```bash\n    docker-compose up --build\n    ```\n\n   This command builds the Node.js application image (as per your Dockerfile), starts the Redis service, and starts the\n   Node.js application service.\n\n    - **Building Service Images:** Docker Compose looks at the **`services`** defined in your **`docker-compose.yml`**\n      file. For services that specify a build context (using the **`build`** key), Docker Compose uses the corresponding\n      **`Dockerfile`** to build a Docker image for each of these services.\n    - **The `-build` Flag:** This flag forces Docker Compose to build (or rebuild) the images for the services, even if\n      an image already exists. It's useful when you have made changes to a service or its Dockerfile and want to ensure\n      that the latest version is used.\n3. **Accessing the Application:**\n\n   Your Node.js application should now be accessible at `http://localhost:4001`.\n\n4. **Shutting Down:**\n\n   To stop and remove the containers, networks, and volumes created by `up`, run:\n\n    ```bash\n    docker-compose down\n    ```\n\n### Additional Notes\n\n- **Data Persistence for Redis:** If you need to persist Redis data, consider defining a volume for the Redis service in\n  your `docker-compose.yml`.\n- **Environment Variables:** If your Node.js application requires environment variables, you can define them in\n  the `docker-compose.yml` file under the `node-app` service using the `environment` key or using an `.env` file.\n- **Custom Redis Configuration:** To use a custom Redis configuration, you can mount a configuration file from your host\n  to the Redis container.\n\nUsing Docker Compose simplifies the management of multi-container Docker applications, making it easy to start, stop,\nand rebuild services in a coordinated manner.\n\n# Networking in Docker Compose\n\n1. **Automatic Network Creation:**\n    - When you run `docker-compose up`, Docker Compose automatically creates a network for your services. By default,\n      this network allows communication between the containers.\n2. **Service Name as Hostname:**\n    - In your `docker-compose.yml`, the services are named `redis-server` and `node-app`. These service names can be\n      used as hostnames within the network. For example, your Node.js app can access the Redis server using the\n      hostname `redis-server`.\n\n### Connecting Node App to Redis Server\n\nIn your Node.js application, when configuring the Redis client, you should use `redis-server` as the hostname to connect\nto the Redis server. Here's an example based on your provided `index.ts` file:\n\n```tsx\n// ... other imports\nimport {createClient} from 'redis';\n\n// Create a Redis client using the service name as the hostname\nconst client: RedisClientType = createClient({\n    url: 'redis://my-redis:6379'\n});\n\n// ... rest of your code\n\n```\n\n### Explanation\n\n- `redis://redis-server:6379`: This tells the Redis client to connect to the Redis server at the\n  hostname `redis-server`, which is the name of your Redis service in `docker-compose.yml`, on the default Redis port\n  6379.\n\n### Benefits\n\n- **Isolation:** Each service runs in its own container, providing an isolated environment.\n- **Scalability:** Services can be scaled independently.\n- **Service Discovery:** Docker Compose network handles service discovery automatically, allowing services to\n  communicate by their names.\n\n# Initiating a multi-containers\n\nRunning the command `docker-compose up --build` initiates a multi-step process involving both building Docker images for\nyour services (if necessary) and then starting those services as defined in your `docker-compose.yml` file. Let's break\ndown what happens when you execute this command:\n\n### 1. Building Images\n\n- **Building Service Images:**\n    - Docker Compose looks at the services defined in your `docker-compose.yml` file.\n    - For services that require building an image (like your `node-app` service which has a `build: .` directive),\n      Docker Compose uses the corresponding `Dockerfile` in the specified context (in your case, the current\n      directory `.`) to build a Docker image.\n    - The `-build` flag forces Docker Compose to build (or rebuild) the images for the services even if an image already\n      exists. This ensures that any changes in the service’s Dockerfile or in the service’s build context are included.\n\n### 2. Creating and Starting Containers\n\n- **Creating Redis Server Container:**\n    - For the `redis-server` service, since it uses an image directly (`image: 'redis'`), Docker Compose pulls the Redis\n      image from Docker Hub if it's not already available locally.\n    - Docker Compose then creates a new container instance based on the Redis image.\n- **Creating Node App Container:**\n    - For the `node-app` service, Docker Compose uses the image built in the previous step.\n    - A new container instance is created based on this image.\n\n### 3. Setting Up Networking\n\n- **Automatic Network Creation:**\n    - Docker Compose sets up a default network for the composed application.\n    - Each container is attached to this network, and each service can communicate with other services using the service\n      names as hostnames (e.g., `redis-server` for the Redis service).\n\n### 4. Exposing Ports\n\n- **Port Mapping:**\n    - For your `node-app` service, Docker Compose maps the port `8081` inside the container to port `4001` on your host\n      machine. This makes your Node.js application accessible via `http://localhost:4001`.\n\n### 5. Running Services\n\n- **Starting Services:**\n    - Both the `redis-server` and `node-app` containers are started.\n    - If there are any dependencies between the services (not in your case), Docker Compose starts the services in\n      dependency order.\n\n### 6. Logs and Monitoring\n\n- **Service Logs:**\n    - By default, Docker Compose streams the output of all the containers to the terminal. This includes logs that would\n      normally output to stdout and stderr.\n\n### 7. Running in the Background\n\n- **Detached Mode (Optional):**\n    - If you want to run the services in the background, you can add the `d` flag (`docker-compose up --build -d`). This\n      will start the containers in detached mode, and you will get the command prompt back.\n\n# Introduction to Restart Policies\n\nDocker provides several restart policies to control the behavior of containers in different situations:\n\n1. **`no`:** This is the default restart policy. The container will not be restarted if it stops or crashes.\n2. **`always`:** The container will always be restarted if it stops. If the container is manually stopped, it is\n   restarted only when the Docker daemon restarts or the container itself is manually restarted.\n3. **`unless-stopped`:** The container will always be restarted unless it is explicitly stopped. Even if the Docker\n   daemon restarts, the container will be restarted unless it was manually stopped before.\n4. **`on-failure`:** The container will be restarted only if it exits with a non-zero exit status (indicative of an\n   error). Optionally, you can specify a maximum number of retries before giving up.\n\n### Implementation of Restart Policies\n\nTo implement restart policies, you specify them when you run a container using the `docker run` command, or you can\ndefine them in a `docker-compose.yml` file for Docker Compose-managed containers.\n\n### Using `docker run`\n\nWhen you start a container with `docker run`, use the `--restart` flag to set the restart policy. Here are some\nexamples:\n\n- **No Restart Policy:**\n\n    ```bash\n    docker run --restart=no my-image\n    ```\n\n- **Always Restart Policy:**\n\n    ```bash\n    docker run --restart=always my-image\n    ```\n\n- **Restart on Failure with Maximum Retries:**\n\n    ```bash\n    docker run --restart=on-failure:5 my-image\n    ```\n\n### Using `docker-compose.yml`\n\nIn a `docker-compose.yml` file, you can specify the restart policy for each service. Here's an example of how to set\ndifferent restart policies:\n\n```yaml\nversion: '3'\nservices:\n  webapp:\n    image: my-webapp\n    restart: always\n\n  redis:\n    image: redis\n    restart: on-failure\n\n  mysql:\n    image: mysql\n    restart: unless-stopped\n```\n\n### Best Practices and Considerations\n\n- **Use Wisely:** Restart policies are helpful for ensuring high availability, but they should be used wisely.\n  Automatically restarting a container that is failing due to a configuration error or a fundamental issue can lead to a\n  restart loop.\n- **Logging and Monitoring:** Implement logging and monitoring to keep track of container restarts and diagnose any\n  issues leading to repeated restarts.\n- **Health Checks:** Combine restart policies with health checks for more robustness. Docker can check the health of\n  your application and restart the container if it becomes unhealthy.\n- **Docker Compose in Production:** When using Docker Compose in production, ensure that your restart policies are\n  correctly set to handle unexpected failures.\n\nRestart policies are a key feature in Docker for managing container lifecycles, especially in production environments\nwhere reliability is critical. By understanding and implementing these policies correctly, you can significantly improve\nthe resilience of your Dockerized applications.\n\n# Final Takeaway\n\n### Architecture Overview of the Node.js and Redis Application\n\n### 1. Components\n\n- **Node.js Application (Service: `node-app`):**\n    - **Function:** Serves as the web server, handling HTTP requests and responses.\n    - **Technology:** Built using Express.js, a popular framework for Node.js.\n    - **Primary Role:** Manages the business logic, which in this case, is tracking the number of visits to the\n      homepage.\n    - **Redis Interaction:** Connects to the Redis server to get and set the visit count.\n    - **Port Exposure:** The service is exposed on port 4001, making it accessible via `http://localhost:4001`.\n- **Redis Server (Service: `my-redis`):**\n    - **Function:** Acts as a data store for the application.\n    - **Technology:** An in-memory data structure store, used as a database, cache, and message broker.\n    - **Role:** Stores the number of visits as a key-value pair.\n    - **Persistence:** By default, Redis data is ephemeral. To persist data, you'd need to configure Redis with a volume\n      in Docker.\n\n### 2. Networking\n\n- **Internal Network:**\n    - Created and managed by Docker Compose.\n    - Both the Node.js application and Redis server are attached to this network.\n    - This setup allows the Node.js application to communicate with the Redis server using the service name `my-redis`\n      as the hostname.\n\n### 3. Data Flow\n\n1. **HTTP Request Handling:**\n    - A user sends an HTTP request to the Node.js application by accessing `http://localhost:4001`.\n    - The Express server in the Node.js application receives the request.\n2. **Retrieving and Updating Visits:**\n    - The Node.js application queries the Redis server to retrieve the current number of visits.\n    - The Redis server responds with the visit count.\n    - The Node.js application increments this number and sends it back to Redis for updating.\n3. **Response to the User:**\n    - The Node.js application then sends a response back to the user with the number of visits.\n\n### 4. Docker Compose Configuration\n\n- Defined in a `docker-compose.yml` file.\n- Specifies the services (`node-app` and `my-redis`), their configurations, and how they are networked together.\n- Ensures that both services can be started, stopped, and managed together, providing a cohesive environment for the\n  application.\n\n### 5. Scalability and Reliability\n\n- **Scalability:** The application can be scaled by increasing the number of Node.js instances, assuming the Redis\n  server can handle the increased load.\n- **Reliability:** Implemented through Docker's restart policies. In case of failures, containers can be automatically\n  restarted based on the policy.\n\n### 6. Security Considerations\n\n- **Network Security:** Communication between the Node.js application and Redis server is internal and not exposed to\n  the external network.\n- **Data Security:** Redis data security needs consideration, especially if sensitive data is stored.\n- **Container Security:** Regular updates to the Docker images and secure configuration are necessary to mitigate\n  security vulnerabilities.\n\n### Conclusion\n\nThe architecture provides a solid foundation for a web application with a Redis backend. It leverages Docker and Docker\nCompose for containerization and orchestration, ensuring ease of deployment and scalability. This setup is ideal for\napplications requiring high-performance data interactions, with the flexibility to adapt to increasing loads and\ncomplexity.","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnawodyaishan%2Fmultiple-docker-example","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnawodyaishan%2Fmultiple-docker-example","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnawodyaishan%2Fmultiple-docker-example/lists"}