blowstack logo

Dockerize Nuxt.js

Part 1 Nginx & MySQL

Last update

20 min.
  1. Structuring Nuxt app for Docker
  2. Creating Dockerfile
  3. Creating docker-compose
  4. Configuring Nuxt
  5. Building and running image
  6. Setup and configuration of Nginx
  7. Setup and configuration of MySQL
  8. Building image for production
  9. Testing production config
  10. Next steps

 

 

Structuring Nuxt app for Docker

 

It's not necesserary to change the default nuxt structrure but it's very recommended. When your app grows the more important a proper docker stucture proves to be usefull. Additionally it's very easy and takes only a minute.

Create a container folder for docker services and paste your current app into it. Next preperate nginx and mysql empty folders. Doing this will enable you changing default configuration of Nginx and MySQL or any other service just by proving proper conf files.

 

 

Creating Dockerfile

 

Inside the root of your app create a Dockerfile. This file is responsible for bulding and running your app on designated port. Nuxt.js is a Node.js app so when creating a new image it's very convenient to inherit from a node image and build on top of that. Take a look at the body of the Dockerfile. There are a few things that may be not clear if you haven't use Docker before. I will explain them now but if you are already familiar with how Docker works just go the the Docker compose section.

FROM node:12.16.3-alpine3.9

RUN mkdir -p /var/www/dockerize-nuxt/nuxt-app
WORKDIR /var/www/dockerize-nuxt/nuxt-app

COPY package*.json ./
RUN npm install

COPY . .

RUN npm run build

EXPOSE 3000

ENV NUXT_HOST=0.0.0.0

ENV NUXT_PORT=3000

CMD [ "npm", "start" ]

 

Add .dockerignore file with at least this minimal content:

.git
.gitignore
node_modules/

 

 

Dockerfile explanation:


 

The first line it's a command for building a node.js image. I recommend you not to use the often proposed in many tutorials the latest version as it can lead to unexpected behaviour. Choose a specific node version and test it before going to production.

Next there are commands for making a new folder for your Nuxt app and changing working directory to this newly created folder. This working directory is exacly the root of your app inside the docker image and you can execute any command that you used to execute before dockering your app (assuming that all dependencies are installed).

Forth and fifth commands respectively copies package.json files with your app dependencies and install them (notice that it's usual step when bulding a new app on production or from repository).

Then copy (COPY . .) the rest app files from current host directory into current working directory of the docker image (/var/www/dockerize-nuxt/nuxt-app). The next RUN npm should be obvious now.

What may not still be clear is expose and next two commands. Expose tells docker service on which port forward your running app to the host system. Remember that your app is actually run by docker not the host system. The host system only runs the docker service. ENV NUXT_HOST and PORT commands (actually envoronment variables) declare internal docker address and port where the app is running, 0.0.0.0 means whole range. These are important because you will run other services which uses different ports that communicate one another in docker service. It works exacly the same as services in your host system but it's separated from your host and this is the core idea behind the docker itself. The only things which is shared between docker and the host is kernel.

The last one command starts our app. You can pass here any command to execute after building process. It's high time to test wheather your app is running properly as a docker image. Let's build and run it!

 

 

Creating docker-compose

 

Create a docker-compose.yml file in the container folder (not the root of your app). From there you will be able to configure and connect other services like MySQL or Nginx. First declare your app service in that way (change folder name and service name for yours). Build should points at the folder with your nuxt app.

 

version: "3.7"

services:
  nuxt-app:
    build: ./nuxt-app
    container_name: nuxt-app
    restart: always
    ports:
      - "3000:3000"
    command: "npm run start"
    networks:
      - nuxt-network
networks:
  nuxt-network:
    driver: bridge
 

 

 


Configuring Nuxt

 

Before building the image, you have to change a little bit in .env nuxt file. Find HOST declaration. Just replace 127.0.0.1 (or localhost) for name of your service declared in docker-compose.yml.

HOST=nuxt-app

In that way an internal Docker address wil be passed to your Nuxt.js. You are ready to build and test your docker image.

 

 

Building and running image

 

Go to the container folder where docker-compose.yml file resides and type:

docker-compose up --build -d

 

Image building process takes a while.  After building thanks to -d parameter your image will start running in the background so it won't block your console. You can check wheather the image is running by typping: 

docker ps

 

or go to 127.0.0.1:3000 to check if your app works.

 

 

Setup and configuration of Nginx

 

Let's add Nginx service to docker-compose.yml.

 


services:
 web-server:
   image: nginx:1.17.10-alpine
   container_name: web-server
   volumes:
     - ./nginx/conf.d/default.conf:/etc/nginx/conf.d/default.conf
     - web-root:/var/www/blowstack
   ports:
     - 80:80
   networks:
     nuxt-network:
   depends_on:
     - nuxt-app
   restart: unless-stopped
volumes:
 web-root

 

We need to configure the server and now it's time to use the empty nginx folder previously created. On the Nuxt.js website there are multiple proposed configs for Nginx but they don't cover docker example.  To make it workable with Nuxt we need to pass to the config docker internal address (highlighted with violet). Below full minimal config. Create a folder named conf.d in the empty nginx folder and then create a file named default.conf. Finaly pass the below configuration to the conf.d file, changing services names if necessary. You should also definetly change server_name to your domain.

If you use local environment don't forget to add in hosts file appropriate line like:

127.0.0.1  local.blowstack.com.

 

default.conf


 

upstream docker {
   server nuxt-app:3000;
 }

map $sent_http_content_type $expires {
   "text/html"                 epoch;
   "text/html; charset=utf-8"  epoch;
   default                     off;
}

server {
   listen          80;             # the port nginx is listening on
   server_name     local.blowstack.com www.local.blowstack.com;    # setup your domain here

   gzip            on;
   gzip_types      text/plain application/xml text/css application/javascript;
   gzip_min_length 1000;

   location / {
       expires $expires;

       proxy_redirect                      off;
       proxy_set_header Host               $host;
       proxy_set_header X-Real-IP          $remote_addr;
       proxy_set_header X-Forwarded-For    $proxy_add_x_forwarded_for;
       proxy_set_header X-Forwarded-Proto  $scheme;
       proxy_read_timeout          1m;
       proxy_connect_timeout       1m;
       proxy_pass                          http://docker; 
   }
}

 

Once again go to the container folder where docker-compose.yml file resides and type:

docker-compose up --build -d

 

Check if the app at your local domain works and move to the MySQL section.

 

 

Setup and configuration of MySQL

 

The last service created during first part of this post will be MySQL. It's very similar to the Nginx one but we need to also change DB_HOST parameter in .env nuxt file. Additionaly if you want overwrite default config just paste it to the mysql folder in a smilar way that we did with Nginx. On purpose I declared 3307 ports because you probably already have running MySQL on 3306 port localy and it will cause errors then.

DB_HOST= db-mysql

You can change db-mysql: to any other descriptive name. This is the name we will use in docker-compose.yml file to define MySQL service and it's need to be the same in both files.

 

services:
  db-mysql:
    image: mysql:8.0
    container_name: db-mysql
    command: '--wait_timeout=28800 --default-authentication-plugin=mysql_native_password'
    volumes:
      - "mysql-data:/var/lib/docker/volumes/blowstack/mysql"
    environment:
      MYSQL_ROOT_PASSWORD: password
      MYSQL_DATABASE: database_name
    ports:
      - "3307:3307"
    restart: always
    networks:
      - nuxt-network
volumes:
  web-root:
  mysql-data:

 

Go to the container folder where docker-compose.yml file resides and type:

docker-compose up --build -d

 

Check if your app communicates with MySQL.

 

 

Building image for production

 

You already have working solution of your app in docker service. But you still doesn't have an image which can be easily distributed. We just built nuxt-app service from local files and it's not docked in the hub, it's still totaly local. You still need local files to change and rebuilt your image. It's time to create and push image of your app to the Docker registry. Notice that we didn't use Dockerfile for Nginx or MySQL services, we just declared ready images from Docker hub repository. We are going to do exacly the same with your app but moreover you will keep it on the private repository accessible only for your team.

First stop all containers:

docker stop $(docker ps -aq)

 

Change directory to root of your app where Dockerfile resides and type (change nuxt-app for the name of your app):

docker build -t nuxt-app .

 

In the meantime go to the docker and create new private repo. 

 

Docker new private repo creation

 

You will be informed about the CLI way of pushing your new image to this repository.

 

Docker new repo push commands

 

In my instance it will be done that way:


docker tag nuxt-app:latest blowstack/nuxt-app
docker push blowstack/nuxt-app:latest

 

 

Testing production config

 

Change nuxt service section in docker-compose file. Replace build by your newly created image

nuxt:
  # build: ./nuxt-app
    image: blowstack/nuxt-app:latest

 

Build all images once again based on the changed docker-compose.yml file.

docker-compose up --build -d

 

Test if it's working in the browser. 

Congrats! From now on you can easily commit changes to your nuxt-app image, push to the registry and run anywhere in minutes without complicated configuration.

 

Next steps

 

You can add any service to work with your nuxt image. In the next parts we will cover more sophisticated services implementations and solve some problems which can cause you a headache when dockerizing Nuxt.js app.

Recent posts

BlowStack 2021
Portfolio Cheat
sheets