Updated at 03/07/2025
What is Portainer ?
Portainer is a GUI-based tool for managing Docker.
I’d like to host projects using Docker on a VPS, and Portainer makes maintenance much easier.
Table of contents
4. Create a container by Portainer
1. Prerequest
- VPS
- Portainer is deployed
- Docker
- Github account
2. Prepare a source code
Create a directory in VPS
~$ mkdir ~/home/<user name>/<project name>
Then add a source code with Dockerfile.
Dockerfile
# Use the latest LTS version of Node.js
FROM node:18-alpine
# Set the working directory inside the container
WORKDIR /app
# Copy package.json and package-lock.json
COPY package*.json ./
# Install dependencies
RUN npm install
# Copy the rest of your application files
COPY . .
# Expose the port your app runs on
EXPOSE 3000
# Define the command to run your app
CMD ["npm", "start"]
3. Register Image to GHCR
However Portainer handles containers like Docker Compose, Portainer itself doesn’t build Docker Image.
So build Docker Image then register it to Github Container Registory(GHCR) to use it in Portainer’s stack.
I prefer to use GHCR because it allows me to host multiple private Images.
-
Build Image. *All process are done under project’s directory.
$ docker build -t <app name>:<version number> . -
Get an Personal Access Token in
Githubto registerDocker ImagetoGHCR. -
Access
GHCRbydocker login. Let’s say we store Personal Access Token in~/ghcr.txt$ cat ~/ghcr.txt | docker login ghcr.io -u <github user name> --password-stdin -
Push
Docker ImagetoGHCR.$ docker tag <Image id> ghcr.io/<github user name>/<repository>/<Image name>:<version number> $ docker push ghcr.io/<github user name>/<repository>/<Image name>:<version number>
4. Create a container by Portainer
Create a new stack to Portainer.
If the app use .env, add environment in the stack.
Stack
services:
app:
image: ghcr.io/<github user name>/<repository>/<image name>:<version number>
container_name: <container name>
volumes:
- /home/<user name>/<...directory>/<project name>/node_modules:/app/node_modules
ports:
- "3000:3000"
stdin_open: true
tty: true
Access the web application from <vps-address>:3000.
5. My trouble shooting
Actually, I was faced un error.
The error-log said that react-start script not found.
It meant that node_modules wasn’t exist in the container.
So I updated Dockerfile like below,
# Use the latest LTS version of Node.js
FROM node:18-alpine
# Set the working directory inside the container
WORKDIR /app
# Copy package.json and package-lock.json
COPY package*.json ./
# Copy the rest of your application files
COPY . .
# Install dependencies
RUN npm install
# Expose the port your app runs on
EXPOSE 3000
# Define the command to run your app
CMD ["npm", "start"]
To debug this situation, I added command: sh to Portainer’s stack.
Since the container was stopped immediately after it was created, I can pose this process by adding it.
Don’t forget to remove it after debugging after then.
Happy dev!😉
Update at Sat, Mar 15, 2025
My initial configuration of the volume in docker-compose.yaml wasn’t correct.
volumes:
- ./node_modules:/app/node_modules
Should be like this.
volumes:
- /home/<user name>/<...directory>/<project name>/node_modules:/app/