Using TypeScript with Docker: A Guide to Containerize Your Applications
Tags: webdev, tutorial, docker, beginners
Published: 2023-06-20 14:16:40

## Introduction

### Prerequisites

Before we get into using Typescript and Docker together, it is important to understand what these technologies are on their own

* ***Typescript*** is a programming language that extends JavaScript by adding new features such as type annotations, class and interface definitions, modules, decorators, and more. It's particularly useful for large-scale projects and for developing robust and maintainable code.
    
* **Docker** is a platform that allows developers to create, deploy, and run applications in containers. Containers are lightweight, portable, and self-sufficient environments that can run on any machine that supports Docker, regardless of the underlying infrastructure, it provides several benefits, including portability, isolation, scalability, automation, and standardization
    

Understanding these two technologies makes it clear why knowing how to combine the two to build and deploy your applications can be beneficial

## Benefits of using TypeScript and Docker

Using Typescript and Docker together gives the clear benefit of having *robust and reliable apps* but there are several more benefits when building and deploying applications:

1. Type safety: TypeScript's type annotations can help catch errors early during development, making the code more predictable and easier to understand. This can reduce the number of bugs in the application.
    
2. Improved development experience: TypeScript's advanced type system also comes with powerful autocomplete capabilities, providing developers with suggestions for properties, methods, and parameters, making coding faster and more efficient.
    
3. Better maintainability: TypeScript's class and interface definitions, modules, and decorators can make the code more organized and reusable, making it easier to maintain and update the application over time.
    
4. Consistency and reliability in deployment: Docker allows you to package your application and its dependencies into a single container, which can be easily deployed to any environment. This makes deployment more consistent and reliable and can help to reduce the number of environment-specific bugs.
    
5. Scalability: Docker allows for easy scaling of applications by running multiple containers, which can handle increased traffic and workloads.
    
6. Portability: Docker containers can be easily moved between different environments, such as development, staging, and production. This ensures consistency and reduces complexity.
    
7. Isolation: Docker allows multiple applications or services to run on the same machine without interfering with each other, improving the security and stability of the application.
    
8. Improved collaboration: Docker provides a consistent set of tools and technologies that can be used across different environments (So no more, *"but it worked on my machine"* from your peers), making it easier for developers to collaborate and share their work.
    

## Setting up a TypeScript and Docker project

Let's take an example of a simple Nodejs application to get/create todos in typescript. (*make sure you have* [***Node***](https://nodejs.org)*,* ***npm and*** [***Docker***](https://www.docker.com/products/docker-desktop/) *installed to follow along)*

### Step 1 - Setting up

To get started open your directory and setup your node app as usual with express.js, or follow the code given below

```bash
npm init -y
npm install express body-parser
```

### Step 2- Adding TypeScript

To add Typescript run the following command

```bash
npm install --save-dev typescript @types/express nodemon ts-node
```

This will install typescript as a dev dependency along with types for express, and nodemon which we will use for testing the app locally along with ts-node

TypeScript uses a file called `tsconfig.json` to configure the compiler options for a project. Create a `tsconfig.json` file in the root of the project directory and paste the following JSON

```json
{
  "compilerOptions": {
    "module": "commonjs",
    "esModuleInterop": true,
    "target": "es6",
    "moduleResolution": "node",
    "sourceMap": true,
    "outDir": "build"
  },
  "lib": ["es2015"]
}
```

At this point, your directory should look like this

```plaintext
--node_modules/ 
--package.json 
--tsconfig.json
```

### Step 3 - Creating the App

Then create `App.ts` file ( you can name it anything you like I prefer App.ts) and paste the code below

```typescript
import express, { Request, Response } from 'express';
import bodyParser from 'body-parser';

interface Todo {
    id: number;
    task: string;
    completed: boolean;
}

const app = express();
app.use(bodyParser.json());
let todos: Todo[] = [
    {id: 1, task: "Take out trash", completed: false},
    {id: 2, task: "Do laundry", completed: true}
];

app.get("/", (req: Request, res: Response) => {
	res.send("Hello World");
});


app.get('/todos', (req: Request, res: Response) => {
    res.send(todos);
});

app.post('/todos', (req: Request, res: Response) => {
    const newTodo: Todo = req.body;
    todos.push(newTodo);
    res.send(newTodo);
});

app.listen(3000, () => {
    console.log('Server is running on port 3000');
});
```

At this point, your directory should be looking like this

```plaintext
--node_modules/
--package.json
--tsconfig.json
--App.js
```

### Step 4 -Time to test the app

To check if the app runs, we already have installed the tools need nodemon which uses ts-node to auto compile and autorun our app with changes, BUT we need to make some changes in our package.json

```json
{
...,
"main": "App.ts",
...,
"scripts":{  
    "dev": "nodemon",
    "start": "node build/App.js",
    "build": "tsc --project ./"
  },
...
}
```

`dev` is used for testing, while the `build` is used to compile our typescript code and `start` to run the compiled javascript app.

To start the test server run the following command

```bash
npm run dev
```

Once nodemon finishes you should see the following

```bash
$ nodemon
[nodemon] 2.0.20
[nodemon] to restart at any time, enter `rs`
[nodemon] watching path(s): *.*
[nodemon] watching extensions: ts,json
[nodemon] starting `ts-node App.ts`
Server is running on port 3000
```

### Step 5 - Setting up Docker

The next step is to set up Docker, we do that by creating a `Dockerfile` and paste the following:

```yaml
FROM node:14-alpine
WORKDIR /app
COPY . .
RUN npm install
RUN npm run build
EXPOSE 3000
CMD ["npm","run", "start"]
```

This is the Dockerfile which is the schema to create your docker image,

the `COPY` command copies everything in the root directory to the app directory inside the docker image, to avoid us also copying the node modules we need to create a `.dockerIgnore` file and add the following inside it,

```makefile
/node_modules

/build
```

Now to create the docker image run this command in your terminal:

```bash
docker build . -t tsdocker
```

This will create the docker image

```bash
docker run -p 3000:3000 tsdocker
```

You can open `HTTP://Localhost:3000` and get the message *Hello World* on your screen and there you have it. You have set up your typescript app with docker. We will further how to deploy with a platform like render, in some future blog

## Conclusion

Using TypeScript and Docker together can bring many benefits to a Node.js application. TypeScript provides a way to catch bugs early on by providing type checking and interfaces, while Docker allows for easy deployment and scaling of the application by packaging it in a lightweight container. Additionally, Docker provides a consistent environment regardless of the underlying infrastructure, which can prevent issues caused by differences between development and production environments. Furthermore, TypeScript and Docker make it simple to test the application in various environments as well as manage infrastructure and scaling. Finally, they can help to improve the overall development and deployment process by automating the building, testing, and deployment of code changes.

However, we haven't covered all the things, some advanced things you can cover on your own or through my future blogs are using `multi-stage build` in `Dockerfile` or using `docker compose` to run multiple containers.