Skip to content

Instantly share code, notes, and snippets.

@rambabu-patidar
Last active August 30, 2026 08:15
Show Gist options
  • Select an option

  • Save rambabu-patidar/81b13f0ebbd4048af20f28f227a180c7 to your computer and use it in GitHub Desktop.

Select an option

Save rambabu-patidar/81b13f0ebbd4048af20f28f227a180c7 to your computer and use it in GitHub Desktop.
Important docker commands and notes.

Docker

Docker is a tool that help us to work with the containers. We can pull the images from it's public docker hub repo and run the images in our machine to work with softwares like nodejs, mongodb, linux which otherwise needs to be installed on our Operating System manually.

Containers are the isolated environments in your system that runs on the top of your systems infrastructure but are in isolation. Containers itself doesn't contain the full operating system but rather it contains some binaries. Docker sits in between our machine Operating system and the Container to manage how we use the our computer resources.

to share the container we create the Images of our container which can be replicted on other machine. Images can also be created from Dockerfile. Image contain set of instruction about how to create the container. Think this as image is an Class and Container is it's Object/Instance.

Docker follows Client Server architecture under the hood. So there are three things :

  • docker cli <- This is our client
  • docker daemon <- This is the server
  • REST API <- This sets communication between cli commands and the daemon.

Docker Commands

  • docker --version : To know the version of the docker
  • docker ps : To list the running containers
    • docker ps -a : To list all the containers running/stopped.
  • docker run ubuntu:latest : This will start running our ubuntu container, replace latest with version number if required, if the iamge is not present it will look in the container registry and then download it.
    • docker run -it ubuntu:latest /bin/bash : start container while opening an interactive terminal session inside the container.
    • docker run -d ubuntu : Run the container in detached mode.
    • docker run -dit --name my-ubuntu ubuntu:latest : If you want the container to stay alive silently in the background so you can connect to it later, combine detached (-d) and interactive flags
    • docker exec -it my-ubuntu bash : if you started the container with previous command then you can enter into it with this command. container when running we use the exec command.
  • docker pull node:<version> : To pull the image from remote registry
  • docker stop containerId : stop the running container.
  • docker container prune : delete all the stopped containers.

Docker pull consist of three command which runs automatically

We can run them one by one too.

  • docker pull node:22-alpine : Ran the container from local image, otherwise pull from the docker hub.
  • docker create node:22-alpine : Creates a new writeable container layer over the specified image and prepares its execution configuration.
  • docker start <container> : Boots up the newly created container, assigns it a process ID, and executes its main startup application or custom script we can attach the flags to these commands to mimic behaviour of docker run
@rambabu-patidar

Copy link
Copy Markdown
Author

NOTE: AI Generated Notes of my actual problems I faced and resolved using different sources on Internet.

🌐 Port Mapping and Data Persistence in Docker Containers

By default, Docker containers are isolated from the host machine and the outside network. If a container runs a process (like a web server) on an internal port, you cannot access it from your computer's browser unless you explicitly map an external port to that internal port.

This guide walks you through a common beginner scenario: creating an app entirely inside an isolated container, running into the "missing port" problem, and fixing it without losing your code.


πŸš€ Part 1: Setting Up the Isolated Container

Let's simulate the problem by creating an isolated container and writing an Express application inside it from scratch.

1. Pull the Image

Alpine Linux is used here because it is a lightweight alternative to heavier distributions like Ubuntu.

docker pull alpine:latest

2. Run the Container in the Background

Run the container using the detached (-d) and interactive (-it) flags so it stays alive silently in the background.

docker run -dit --name alpine-01 alpine:latest

3. Enter the Container Terminal

Open an interactive shell inside your running container.

πŸ’‘ Note: Alpine Linux uses sh as its default shell. Ubuntu containers use bash.

docker exec -it alpine-01 sh

πŸ› οΈ Part 2: Building the Express App Inside the Container

Now that you are inside the container's terminal (/ #), perform the following commands to set up a Node.js web server.

1. Install Node.js and NPM

Alpine uses the apk package manager. Update the repository lists and install Node.js:

apk update
apk add nodejs npm

2. Initialize the Project

Create a new directory for your app, navigate into it, and initialize NPM:

mkdir express-app
cd express-app
npm init -y

3. Install Dependencies

Install Express for the server and Nodemon to automatically restart the server during code changes:

npm install express nodemon

4. Create and Edit main.js

Create a server script file using the vi text editor:

vi main.js

Press i to enter Insert Mode, paste the following code, then press Esc, type :wq or :x, and press Enter to save and exit:

const express = require('express');
const app = express();
const PORT = 3000;

app.get('/', (req, res) => {
    res.send('Hello World from Inside Docker!');
});

app.listen(PORT, () => {
    console.log(`Server is running internally on port ${PORT}`);
});

5. Update package.json

Open package.json using vi:

vi package.json

Modify the "scripts" section to include the start script. Ensure your JSON format is strict (do not leave a trailing comma at the end of the last script line, or NPM will crash!):

"scripts": {
  "start": "nodemon main.js"
}

6. Start the Server

npm start

The terminal will show that your app is listening on internal port 3000.

πŸ›‘ The Problem:

If you open your host computer's browser and go to http://localhost:3000, it will not load. The container is isolated, and no external port is listening to the internal process.


πŸ—οΈ Part 3: Solving the Problem with Port Mapping

Docker does not allow you to add port mappings to a container that is already running or created(IMP Read It again.). However, you can save your current container state (including all your written code and installed packages) into a new image.

1. Exit the Container

Stop your running node server with Ctrl + C, then type exit to go back to your laptop's terminal:

exit

2. Commit the Container into a New Image

Freeze your current container state (with your code inside) and name this custom image express-app-container-image:

docker commit alpine-01 express-app-container-image

3. Stop the Old Container

Stop the old isolated container to free up system resources and names:

docker stop alpine-01

4. Run the New Image with Port Mapping (-p)

Spin up a brand-new container from your saved image. Use the -p flag to map an external port (e.g., 8080) to the container's internal port (3000):

docker run -dit --name alpine-01-fixed -p 8080:3000 express-app-container-image

5. Start Your App and Verify

Enter the new, fixed container terminal:

docker exec -it alpine-01-fixed sh

Navigate back to your project directory and start the server:

cd express-app
npm start

Now, open your computer's browser and visit: http://localhost:8080
You will see the "Hello World from Inside Docker!" message!


⚠️ Important Rules About Data Persistence

When working with containers, keep these filesystem rules in mind:

  • Stopping and Starting (docker stop / docker start): You will not lose your data. If you stop alpine-01-fixed and start it tomorrow, your code and configurations remain safe inside that container instance.
  • Deleting (docker rm): You will lose your data. If you delete a container instance, the isolated file system inside it is permanently destroyed. To avoid losing code permanently in production, developers link folders from their host computer using Volumes or Bind Mounts (-v). (We will cover Volumes and Bind Mounts on some other day).

⚑ Alternative: The Docker Way (Fast & Automated)

If your primary goal is simply to build a Node.js application, installing Node manually inside a blank Linux OS container is slow and repetitive.

Professionals use official, pre-configured images to keep their environment entirely disposable, automated, and ready to go in a single command line:

docker run -dit --name my-node-app -p 8080:3000 node:alpine

Why this is better:

  1. Pre-installed Stack: The node:alpine image comes with Alpine Linux, Node.js, and npm already fully optimized and configured out of the box.
  2. Instant Port Mapping: By including -p 8080:3000 right from the beginning, you never have to worry about running into an isolation issue or committing custom images later.

@rambabu-patidar

Copy link
Copy Markdown
Author

πŸ“‚ Real-Time Code Syncing with Docker Bind Mounts

This guide covers how to link a local folder on your host machine to a running Docker container. This allows you to write code in your local text editor (like VS Code) and have it execute instantly inside a containerized environment without losing data.


πŸš€ Part 1: Initializing the Local Environment

1. Create a Project Folder

Open your local terminal (Git Bash, PowerShell, or CMD) and create your workspace:

mkdir docker-node-project
cd docker-node-project

2. The Mounting Command (Terminal Shortcuts)

To link your folder, you must spin up the container using a Bind Mount (-v) and a Working Directory (-w) flag. Choose the command that matches your terminal:

  • Git Bash (Windows): (Requires an extra forward slash / to stop path scrambling)
    docker run -dit --name local-node-env -p 8080:3000 -v /"\$(pwd)":/app -w /app node:alpine
  • PowerShell (Windows):
    docker run -dit --name local-node-env -p 8080:3000 -v \${PWD}:/app -w /app node:alpine
  • Command Prompt / CMD (Windows):
    docker run -dit --name local-node-env -p 8080:3000 -v %cd%:/app -w /app node:alpine

πŸ’‘ Alternative: Using Hardcoded Absolute Paths

Instead of relying on terminal variables like $(pwd) or %cd%, you can explicitly type out the exact absolute path to your folder. This works reliably across different terminal windows:

docker run -dit \
  --name local-node-env \
  -p 8080:3000 \
  -v "C:\Users\Lenovo\Desktop\docker-node-project":/app \
  -w /app \
  node:alpine

(Ensure you wrap the Windows path in quotes if your folder names contain spaces!)


πŸ—οΈ Part 2: Terminal Discipline (Where to Run Commands)

When using bind mounts, your local computer folder and the container folder are a single, synced space. However, your laptop and the container have completely different operating systems and engines.

You must be disciplined about where you type your commands:

Command Where to Run It Why? What Happens If You Do It Wrong?
Code Editing (Ctrl + S, writing JS) Local Laptop (VS Code) You get to use your native desktop UI, extensions, and themes smoothly. Editing files inside the container terminal forces you to use raw terminal tools like vi.
npm install Inside Container (docker exec) The container is running Alpine Linux. It compiles packages specifically for Linux architectures. If run on Windows, it creates Windows binaries. The Linux container will crash with Invalid Win32 application errors.
npm start Inside Container (docker exec) The application process must run inside the isolated Docker network to use the -p port mapping. If run on your laptop, the app runs natively on Windows, completely bypassing Docker and its configuration.

πŸ“ Part 3: Writing Code and Syncing Files

1. Create files locally

Open the docker-node-project folder in VS Code on your laptop and create these two files:

package.json

{
  "name": "docker-mount-test",
  "version": "1.0.0",
  "main": "server.js",
  "scripts": {
    "start": "nodemon -L server.js"
  },
  "dependencies": {
    "express": "^4.19.2"
  },
  "devDependencies": {
    "nodemon": "^3.1.0"
  }
}

server.js

const express = require('express');
const app = express();

app.get('/', (req, res) => {
    res.send('Live syncing is working beautifully!');
});

app.listen(3000, () => {
    console.log('Containerized app listening on port 3000');
});

2. Execute within the Container Environment

Following the discipline rules above, open an execution session into your container to install and run the stack:

# 1. Enter the container terminal
docker exec -it local-node-env sh

# 2. Install packages inside Linux environment
npm install

# 3. Start the application
npm start

(Check your laptop folderβ€”the node_modules folder generated inside the container has successfully synced backward to your local Windows computer filesystem!)


πŸ› οΈ Part 4: Overcoming the Windows File-System Trap

The Problem: Nodemon doesn't reload on file save

When you save a file in Windows, the underlying Linux filesystem inside the container does not always receive the file-change notification event across the Docker Desktop file-sharing bridge. Standard nodemon will sit idle and miss your code changes.

The Fix: Legacy Watch (Polling)

You must force Nodemon to actively scan and poll the filesystem for changes by adding the -L (or --legacy-watch) flag.

Ensure your package.json start script uses the flag:

"start": "nodemon -L server.js"

Alternatively, trigger it manually inside the container shell using:

npx nodemon -L server.js

With polling enabled, saving your server.js in VS Code will now instantly trigger a server restart inside the container. You only need to manually refresh your browser at http://localhost:8080 to see updates.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment