Dockerfile for Typescript
Using docker for local development and deployment makes it easy to get away from the "it works on my machine" problem. By having an artifact that can be rebuild in the same way each time will greatly add to the stability of any application.
Create a dockerfile
For a typescript project, I'm using my Typescript for CommonJS example.
├── .gitignore
├── .nvmrc
├── package.json
├── src
│ └── index.ts
├── tsconfig.json
└── yarn.lock
tree -a --gitignore -I .git
The package.json has a build and start script
"scripts": {
"build": "rimraf ./dist && tsc",
"start": "node dist/index.js",
"dev": "tsx src/index.js"
}
Here is a sample Dockerfile
FROM node:22-bookworm
WORKDIR /app
COPY package.json yarn.lock ./
RUN yarn install --frozen-lockfile --ignore-scripts
# Copy the rest of the application
COPY . .
# build the code
RUN yarn build
CMD [ "npm", "start" ]
Dockerfile
Don't forget to include a .dockerignore
file to keep your context small, see my article on Your Docker Build Context Is Bigger Than You Think about why.
node_modules
dist
.env
.vscode
*.log
.dockerignore
Build and Run
Now build it
docker build -t dockerfile-typescript-example:latest .
And run it. Use -it
to make sure it doesn't exit. To exit press ctrl-c.
docker run -it dockerfile-typescript-example:latest
> prisma-typescript-example@0.1.0 start
> node dist/index.js
hello world!!
^C
Goodbye!
Local Development
Docker compose is a great way to do local development. Let's look at adding this app and utilizing the watch feature to update the running app when it is changed or rebuilt due to new packages being added.
The docker-compose.yml file. Note that the tty is set to true as the example is a cli app. If you are using a web app, such as express, then this isn't necessary.
services:
app:
build: .
tty: true
develop:
watch:
- action: sync+restart
path: src/
target: /app/src
- action: rebuild
path: package.json
command: yarn dev
docker-compose.yml
Make sure it builds:
docker compose build
Run it with:
docker compose up --watch
⦿ Watch enabled
Attaching to app-1
yarn run v1.22.22
$ tsx src/index.js
app-1 | hello world!!
⦿ Syncing service "app" after 1 changes were detected
⦿ service(s) ["app"] restarted
app-1 exited with code 0
yarn run v1.22.22
$ tsx src/index.js
app-1 | hello world, again!!
And when I edit src/index.ts it will resync and restart the service.
If I add a package to the package.json file it will rebuild.
⦿ Rebuilding service(s) ["app"] after changes were detected...
[+] Building 0.0s (0/0)
⦿ service(s) ["app"] successfully built
app-1 exited with code 1
app-1 has been recreated
yarn run v1.22.22
$ tsx src/index.js
app-1 | hello world, again!!
I've shared this project on github as an example https://github.com/markcallen/dockerfile-typescript-example
Now we have created a Dockerfile and a docker-compose.yml file, allowing us to use the Dockerfile for both local development and deployment to production.
Now let's create a devcontainer to help with an easy-to-use development environment.