### First optimisation: using a .dockerignore file and multi-stage build
The first optimization that we can do is using a `.dockerignore` file. Just like a `.gitignore` file, a `.dockerignore` file allows us to exclude file and folders that we don't want to include in the docker image that we are building.
Here's the `.dockerignore` file that I added to this simple project to mainly exclude the dark hole that node_modules are `node_modules`:
```
node_modules
npm-debug.log
Dockerfile
.dockerignore
.git
.gitignore
build
assets
```
In our context, this command only optimizes the build time and not the build size, as the `309 MB` that the node_modules folder occupies are not needed to build the docker imagen but as we run the `npm install` command in any case inside the Dockerfile, this folder is generated and included from inside the Dockerfile.
A better optimisation of the image is to use multi-stage build. Multi-stage builds allows us to include only what is necessary to run the image, and to not include the build files or node_modules for example.
Here's the new version of the `Dockerfile` using multi-stage build:
```Dockerfile
# Build stage of the application
FROM node:18 AS build
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build
# Production stage to run the application
FROM node:18 AS production
COPY --from=build /app/build /prod
RUN npm install --global serve
EXPOSE 3000
CMD ["serve", "prod/"]
```
You can run the following command to build the image:
```shell
docker build -t 'react-multistage' .
```
You can run the following command to verify that the new image size is smaller than the previous one:
```shell
docker image ls
```
I am still usig Nushell on my end to have a pretty print and filter on the images that I want which gives me the following output:

### Première optimisation: utilisation de .dockerignore et multi-stage
Une des première optimisation que l'on peut faire est d'utiliser un fichier `.dockerignore`. Tout comme un fichier `.gitignore`, le fichier `.dockerignore` permet de ne pas include certains dossiers ou fichier qui ne sont pas nécessaire pour l'image que l'on construit.
Voici le `.dockerignore` que j'ai rajouté à ce simple projet pour notamment éviter d'inclure le trou noir qu'est le dossier `node_modules`:
```
node_modules
npm-debug.log
Dockerfile
.dockerignore
.git
.gitignore
build
assets
```
Cependant, ce que cette commande optimise est le temps du build de l'image, car les `309 MB` qu'occupe actuellement ce dossier ne sont pas nécessaire à inclure dans l'image lors du build de celle-ci, mais comme nous lançons la commande `npm install` dans tous les cas dans le Dockerfile, ils sont réinstallé et ré-inclut dans l'image.
Une meilleure optimisation de l'image est d'utiliser le multi-stage build. Le multi-stage build permet de n'inclure que ce qui est nécessaire pour exécuter votre programme et de ne pas inclure les fichier de build ou les node_modules par exemple.
Voici la nouvelle version du `Dockerfile` découpé en multi-stage:
```Dockerfile
# Build stage of the application
FROM node:18 AS build
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build
# Production stage to run the application
FROM node:18 AS production
COPY --from=build /app/build /prod
RUN npm install --global serve
EXPOSE 3000
CMD ["serve", "prod/"]
```
Vous pouvez lancer la commande suivante pour construire l'image:
```shell
docker build -t 'react-multistage' .
```
Vous pouvez relancer la comande suivante pour vérifier que la taille a bien diminué cette fois-ci:
```shell
docker image ls
```
Pour ma part j'utilise toujours Nushell pour avoir cette belle présentation des résultats filtré:

L'image pèse maintenant `44 MB` de moins, on a une image 1.27 fois plus petite, soit une diminution de la taille de 21.67% !