/building-an-application-with-a-rabbitmq-acorn-service
Step 1 – Signing up with CloudAMQP
This is the fourth part in a series focused on teaching the fundamentals of building and developing applications using Acorn. In the previous post of this series we enhanced the Acornfile of the VotingApp defining volumes for both db and redis containers. In this post we will use Acorn’s development mode to accelerate and ease the development workflow.
In development mode , Acorn allows you to make changes to the source code and see it updated inside the app containers in real time. In this mode Acorn will watch the local directory for changes and synchronize them to the running Acorn app. To activate the development mode we need to use the -i flag when running the app.
In this post we will focus on the result microservice which is developed with Node.js. If you have a look into the folder containing the application code, you will see 2 build targets are defined in the Dockerfile: the first one is named dev, the second one production:
WORKDIR /app COPY . . EXPOSE 5000 FROM base as dev ENV NODE_ENV=development RUN npm ci CMD ["npm", "run", "dev"] FROM base as production ENV NODE_ENV=production RUN npm ci --production CMD ["npm", "start"]
– when the image is built for the dev target, the command npm run dev runs nodemon under the hood. nodemon is a process which watches the code changes and which is able to relaunch the application
– when the image is built for the production target, the command npm start runs the standard node binary. No hot reload is possible in that case
Before running the Acorn application in development mode we need to modify the Acornfile is bit to make sure that if the dev mode is detected:
build: { target: std.ifelse(args.dev, "dev", "production") context: "./result" } if args.dev { dirs: { "/app": "./result" } } ports: "5000/http" env: { "POSTGRES_USER": "secret://db-creds/username" "POSTGRES_PASSWORD": "secret://db-creds/password" } }
Note: Acorn provides many useful functions such as the std.ifelse , an helper to perform an if…else…end statement on a single line. All the function available are listed in the function library documentation.
You can now update the application running it in development mode:
undefined
note: in development mode you’ll notice that the logs of each containers are streamed to the console
Once the application is up and running you can modify the server.js file located in the result folder and see that changes automatically been taken into account making the container’s process to restart.
Below is an example of logs you can get for the result service following a change in server.js:
We illustrated above the development mode for the result microservice but the same principles would apply for the other microservices as well. We can change the Acornfile modifying the definition of the voteui, vote and resultui containers to ensure the development mode is working fine for those ones as well.
if args.dev { dirs: { "/usr/share/nginx/html": "./vote-ui" } } build: { context: "./vote-ui" } ports: publish : "80/http" } vote: { build: { target: std.ifelse(args.dev, "dev", "production") context: "./vote" } if args.dev { dirs: { "/app": "./vote" } } ports: "5000/http" } resultui: { build: { target: std.ifelse(args.dev, "dev", "production") context: "./result-ui" } if args.dev { dirs: { "/app": "./result-ui" } } ports: publish : "80/http" }
Once you have modified the Acornfile you can update the application one more time:
undefined
We can go one step further and make sure volumes are not used when the app is run in development mode.
In order to do that we need to:
if !args.dev { "db": { size: "100M" } "redis": { size: "100M" } } }
labels: { component: "redis" } image: "redis:7.0.5-alpine3.16" ports: "6379/tcp" dirs: { if !args.dev { "/data": "volume://redis" } } }
labels: { component: "db" } image: "postgres:15.0-alpine3.16" ports: "5432/tcp" env: { "POSTGRES_USER": "secret://db-creds/username" "POSTGRES_PASSWORD": "secret://db-creds/password" } dirs: { if !args.dev { "/var/lib/postgresql/data": "volume://db" } } }
In this example we explained how to use Acorn development mode to speed up the whole development cycle of the application as changes done locally are immediately taken into account by the running containers.
In the next post of the series we’ll discuss about args and profile which are often used to provide a dynamic configuration to an application. If you’d like to learn more about working with Acorn, you can register for an upcoming live online training.
Luc Juggery is a software engineer with 18+ years of experience and co-founder of 2 startups located in Sophia-Antipolis, southern France. You can chat with him on Twitter, read more of his work on Medium, find his tutorials on YouTube, or take one of his Docker or Kubernetes training courses on Udemy.