Use CarboneJS into Docker Container 🐳

Steeve - Apr 26 '20 - - Dev Community

Introduction

This tutorial is about using CarboneJS into Docker containers and generating an invoice as PDF. It can be useful to split the Carbone process into containers to generate the reports.

This article is part of a series:

Preparing the template

The following document invoice_template.odt has been made with Libre Office. All markers {d.} in the document will be replaced by data.

Invoice Template

Preparing the data to inject

Bellow is the JSON data to inject into the template. The key names should match the template markers. The file is called invoice_data.json:

{
  "id": 42, # the corresponding marker to use in the template is {d.id}
  "date": 1492012745, # {d.date}
  "company": {
    "name": "awesomeCompany", # {d.company.name}
    "address": "77 Bleecker Street", # {d.company.address}
    "city": "Manhattan, New York",
    "postalCode": 10012
  },
  "customer": {
    "name": "customerName",
    "address": "2 Random Street",
    "city": "Far Far Away",
    "postalCode": 85000
  },
  "products": [
    {
      "name": "product 1", # {d.products[i=0].name}
      "priceUnit": 0.1,
      "quantity": 10,
      "priceTotal": 1
    },
    {
      "name": "product 2",
      "priceUnit": 0.2,
      "quantity": 20,
      "priceTotal": 4
    }
  ],
  "total": 5
}
Enter fullscreen mode Exit fullscreen mode

Carbone setup

Firstly, install the Carbone dependency:

# NPM
$ npm install carbone --save
# YARN
$ yarn add carbone
Enter fullscreen mode Exit fullscreen mode

In the index.js, insert the code to generate the report:

/** 1 . dependencies */
const carbone = require('carbone');
const fs = require('fs');

/** 2 . input template file name and output file name */
const _fileInputName = './invoice_template.odt';

/** 3 . Data to inject */
const _data = require("./invoice_data.json")

/** 4 . Options object */
const _options = {
  convertTo: 'pdf',
  reportName: 'invoice_{d.id}.pdf'
};

/** 5 . Call carbone render function */
carbone.render(_fileInputName, _data, _options, (err, result, reportName) => {
  if (err) {
    console.log(err);
  } else {
    fs.writeFileSync('./build/' + reportName, result);
  }
  process.exit();
});
Enter fullscreen mode Exit fullscreen mode

That's a lot of code, here is the explanation:

  1. It instantiates Carbone.
  2. Definition of the filename template.
  3. Import the JSON data.
  4. An optional object can be passed to Carbone to define complement data, variables, translations, and more... In this case, the convertTo option defines the file export type and reportName the report filename.
  5. The Carbone render function generates the report by taking as argument the template file name, the data object, and the options. If it succeeds, the final report is created with fs.writeFileSync. If the rendering fails, the callback function responds by filling the err variable. In this case, the error will be printed. To make the program stop at the end, process.exit() is necessary.

Preparing the Dockerfile

Before diving into Containers, you may need Docker basics before continuing. You can learn from the official Docker documentation 🐳 OR awesome dev.to tutorials ⚡️.

To make Carbone work properly, the environment needs to be defined:

  • Required: Carbone is based on NodeJs (Node 8 minimum).
  • Optional: Libre Office has to be installed to generate the report into PDF format. Learn more about PDF export.

Let's create a Dockerfile with these specifications:

# 1
FROM ideolys/carbone-env-docker

# 2
ENV DIR /app

# 3
WORKDIR ${DIR}

# 4
COPY . ${DIR}

# 5
RUN npm install

# 6
CMD [ "node", "index.js" ]
Enter fullscreen mode Exit fullscreen mode

Details about this Dockerfile:

  1. "ideolys/carbone-env-docker" is a Node 8 image with Libre Office already Installed. You can check the DockerFile on Github. During the docker run command, the image will be pulled from the Docker Hub.
  2. the ENV instruction defines the app directory into environment variables
  3. the WORKDIR instruction sets the working directory to /app
  4. the COPY instruction copies the local files and directory into the working directory
  5. Command to install the npm dependencies
  6. the CMD instruction is used to define the default command to run. In our case, node index.js is executed.

Before continuing, here is the actual project directory:

Project directory

Run the following command on your terminal to build the image from the Dockerfile :

$ docker build . -t myapp-carbone:1.0
Enter fullscreen mode Exit fullscreen mode

On success, the message "Successfully tagged myapp-carbone:1.0" appears at the end of the process.

To verify if the image has been built, run docker image ls:
Alt Text

Finally, run the image in a container through this command:

$ docker run -v $(pwd)/build:/app/build myapp-carbone:1.0
$ # `-v` argument is used to persist and save the generated report into a `build` folder
Enter fullscreen mode Exit fullscreen mode

After running the container, the generated report appears on the build folder 🎉 Let's take a look:

Generated report

The use of Docker can be pushed further, for example, use a template directory as a volume to share templates with the container.

Conclusion

First, We covered how to set up a Carbone project with an invoice ODT template and the data to inject. Thereafter, we created the Dockerfile to make Carbone work properly. Finally, we executed the container to generate the invoice.

Do not hesitate to contact me. If you need information about Carbone, here is an article to learn the basis: Carbone Turorial - Fast and Easy report generator (as fast as a spaceship 🚀)

Leave a like to support my article or follow me to be notified of my next articles 🔥

Thanks for reading!

. . . .