Docker : NodeJS and MySQL app with React in a docker
The app consists of a client using React.js frontend, Node.js is used as a backend server with Express for REST APIs and MySQL db.
The React client sends HTTP Requests and retrieves HTTP Responses using Axios, consume data on the components. React Router is used for navigating to pages. The Node.js Express exports REST APIs and interacts with MySQL Database.
Picture source: Building Data Science Web Application with React, NodeJS, and MySQL
To run our app, we have to do the following:
- install node, for mac,
brew install node
- clone a repo
- install packages under server directory,
npm install
- docker-compose up
Let's start!
Clone repo:
$ git clone https://github.com/Einsteinish/react-nodejs-mysql-docker-compose.git $ cd react-nodejs-mysql-docker-compose
Install the dependencies:
$ npm version { 'web-samples': '1.0.0', npm: '6.14.5', ares: '1.16.0', brotli: '1.0.7', cldr: '37.0', icu: '67.1', llhttp: '2.0.4', modules: '83', napi: '6', nghttp2: '1.41.0', node: '14.5.0', openssl: '1.1.1g', tz: '2019c', unicode: '13.0', uv: '1.38.0', v8: '8.3.110.9-node.23', zlib: '1.2.11' } $ cd server $ npm install
The npm
(node package manager) is a dependency/package manager we get out of the box when we install Node.js.
It provides a way for developers to install packages both globally and locally.
Note that npm
by itself doesn't run any packages.
If we want to run a package using npm
, we must specify that package in our package.json file.
When executables are installed via npm packages, npm creates links to them:
- local installs have links created at the ./node_modules/.bin/ directory.
- global installs have links created from the global bin/ directory, for example: /usr/local/bin on Linux.
We'll be using 4 services: mysql, phpmyadmin, server, and client:
- mysql will use the extension fields declared for host, database, user and password (and a root password of its own just in case) to enable connections for the other services. The port 3306 is exposed as the default port.
- phpmyadmin is to view the databases and manually edit if needed. It will depend on the mysql service so this service will run before it upon start, and it is linked to it to enable use of the credentials defined (host, database, user, password) when navigating to http://localhost:8080 to access the database. The PMA_HOST defines the address of the mysql server.
- server refers to the nodeJS app. It will be built with its own Dockerfile, and it will run before the mysql service. It will expose the port 8000 and use a variable, REACT_APP_SERVER_PORT, to allow the express server to work. MYSQL_HOST_IP allows us to resolve the mysql service's host IP address to map it to the mysql connection.
- client refers to the React app. Its build attribute will search for a Dockerfile inside the client folder. The NODE_PATH environment variable allows for the app to recognize its src folder as the start point for aliases to work. It also makes of the extension fields, but only to use REACT_APP_SERVER_PORT. Since the default port in a react app done with CRA is 3000 , this port will be exposed. We provide volumes for the src folder to store codes.
Here is our compose file, docker-compose.yml:
version: "3.4" x-common-variables: &common-variables MYSQL_USER: sampleuser MYSQL_PASSWORD: samplepassword MYSQL_DATABASE: sampledb REACT_APP_SERVER_PORT: 8000 services: mysql-db: image: mysql:5.7 container_name: mysql_container environment: <<: *common-variables MYSQL_HOST: localhost MYSQL_ROOT_PASSWORD: root ports: - 3306:3306 restart: unless-stopped volumes: - ./db/sample.sql:/docker-entrypoint-initdb.d/sample.sql phpmyadmin: depends_on: - mysql-db image: phpmyadmin/phpmyadmin container_name: phpadmin_container environment: PMA_HOST: mysql-db links: - mysql-db:mysql-db ports: - 8080:80 restart: always server: build: ./server container_name: node_server_container depends_on: - mysql-db environment: <<: *common-variables MYSQL_HOST_IP: mysql-db ports: - 8000:8000 volumes: - ./server:/app links: - mysql-db command: npm start client: build: ./client container_name: client_container environment: <<: *common-variables NODE_PATH: src ports: - 3000:3000 volumes: - ./client/src:/app/src links: - server command: npm start
- build tells how we want our container built.
It can be specified either as a string containing a path to the build context (in our case)server: build: ./server
or, as an object with the path specified under context and optionally Dockerfile and args:server: build: context: ./server dockerfile: Dockerfile args: buildno: 1
- ports vs expose:
port: we can either specify both ports (host:container), or just the container port (in this case, a random host port will be chosen).
The ports in docker-compose.yml will be shared among different services started by the docker-compose. So, in our case, we do not need the expose. We only need to specify the ports.
expose: exposing ports without publishing them to the host machine. They'll only be accessible to linked services. Only the internal port can be specified.
- volumes:
volumes are the persistent data connected to each container. We're duplicating parts of our container and its dependencies in a way that when we throw the container away and start a new one it’ll have that cache to avoid the time of reinstalling everything.
The syntax uses the generic [SOURCE:]TARGET[:MODE] format, where SOURCE can be either a host path or volume name.
TARGET is the container path where the volume is mounted.
Standard modes are ro for read-only and rw for read-write (default). - links: we use this to make connections between containers.
- environment: the variables can be either an array or a dictionary.
Run docker-compose build
:
$ docker-compose build
This will skip both images for mysql and phpmyadmin, and will build the images for client and server.
Now that the images are ready, run docker-compose up -d
to start the four images in detached mode:
$ docker-compose up -d ... Creating mysql_container ... done Creating phpadmin_container ... done Creating node_server_container ... done Creating client_container ... done
To check which containers are running:
$ docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 5b2ca502b3a6 react-nodejs-mysql-docker-compose_client "docker-entrypoint.s…" 33 seconds ago Up 31 seconds 0.0.0.0:3000->3000/tcp client_container 2c6002db4499 react-nodejs-mysql-docker-compose_server "docker-entrypoint.s…" 35 seconds ago Up 32 seconds 0.0.0.0:8000->8000/tcp node_server_container 3ae59b164931 phpmyadmin/phpmyadmin "/docker-entrypoint.…" 35 seconds ago Up 32 seconds 0.0.0.0:8080->80/tcp phpadmin_container f7b1e7203fde mysql:5.7 "docker-entrypoint.s…" 36 seconds ago Up 34 seconds 0.0.0.0:3306->3306/tcp, 33060/tcp mysql_container
On the browser, navigate to http://localhost:3000 for the react app. With the developer console opened, we get the following:
phpadmin (http://localhost:8080):
We can see the contents of the table:
- How to create a React frontend and a Node/Express backend and connect them
- Building a React App that connects to MySQL via NodeJS using Docker
- https://github.com/gfcf14/react-node-mysql-docker-boilerplate.git
Docker & K8s
- Docker install on Amazon Linux AMI
- Docker install on EC2 Ubuntu 14.04
- Docker container vs Virtual Machine
- Docker install on Ubuntu 14.04
- Docker Hello World Application
- Nginx image - share/copy files, Dockerfile
- Working with Docker images : brief introduction
- Docker image and container via docker commands (search, pull, run, ps, restart, attach, and rm)
- More on docker run command (docker run -it, docker run --rm, etc.)
- Docker Networks - Bridge Driver Network
- Docker Persistent Storage
- File sharing between host and container (docker run -d -p -v)
- Linking containers and volume for datastore
- Dockerfile - Build Docker images automatically I - FROM, MAINTAINER, and build context
- Dockerfile - Build Docker images automatically II - revisiting FROM, MAINTAINER, build context, and caching
- Dockerfile - Build Docker images automatically III - RUN
- Dockerfile - Build Docker images automatically IV - CMD
- Dockerfile - Build Docker images automatically V - WORKDIR, ENV, ADD, and ENTRYPOINT
- Docker - Apache Tomcat
- Docker - NodeJS
- Docker - NodeJS with hostname
- Docker Compose - NodeJS with MongoDB
- Docker - Prometheus and Grafana with Docker-compose
- Docker - StatsD/Graphite/Grafana
- Docker - Deploying a Java EE JBoss/WildFly Application on AWS Elastic Beanstalk Using Docker Containers
- Docker : NodeJS with GCP Kubernetes Engine
- Docker : Jenkins Multibranch Pipeline with Jenkinsfile and Github
- Docker : Jenkins Master and Slave
- Docker - ELK : ElasticSearch, Logstash, and Kibana
- Docker - ELK 7.6 : Elasticsearch on Centos 7
- Docker - ELK 7.6 : Filebeat on Centos 7
- Docker - ELK 7.6 : Logstash on Centos 7
- Docker - ELK 7.6 : Kibana on Centos 7
- Docker - ELK 7.6 : Elastic Stack with Docker Compose
- Docker - Deploy Elastic Cloud on Kubernetes (ECK) via Elasticsearch operator on minikube
- Docker - Deploy Elastic Stack via Helm on minikube
- Docker Compose - A gentle introduction with WordPress
- Docker Compose - MySQL
- MEAN Stack app on Docker containers : micro services
- MEAN Stack app on Docker containers : micro services via docker-compose
- Docker Compose - Hashicorp's Vault and Consul Part A (install vault, unsealing, static secrets, and policies)
- Docker Compose - Hashicorp's Vault and Consul Part B (EaaS, dynamic secrets, leases, and revocation)
- Docker Compose - Hashicorp's Vault and Consul Part C (Consul)
- Docker Compose with two containers - Flask REST API service container and an Apache server container
- Docker compose : Nginx reverse proxy with multiple containers
- Docker & Kubernetes : Envoy - Getting started
- Docker & Kubernetes : Envoy - Front Proxy
- Docker & Kubernetes : Ambassador - Envoy API Gateway on Kubernetes
- Docker Packer
- Docker Cheat Sheet
- Docker Q & A #1
- Kubernetes Q & A - Part I
- Kubernetes Q & A - Part II
- Docker - Run a React app in a docker
- Docker - Run a React app in a docker II (snapshot app with nginx)
- Docker - NodeJS and MySQL app with React in a docker
- Docker - Step by Step NodeJS and MySQL app with React - I
- Installing LAMP via puppet on Docker
- Docker install via Puppet
- Nginx Docker install via Ansible
- Apache Hadoop CDH 5.8 Install with QuickStarts Docker
- Docker - Deploying Flask app to ECS
- Docker Compose - Deploying WordPress to AWS
- Docker - WordPress Deploy to ECS with Docker-Compose (ECS-CLI EC2 type)
- Docker - WordPress Deploy to ECS with Docker-Compose (ECS-CLI Fargate type)
- Docker - ECS Fargate
- Docker - AWS ECS service discovery with Flask and Redis
- Docker & Kubernetes : minikube
- Docker & Kubernetes 2 : minikube Django with Postgres - persistent volume
- Docker & Kubernetes 3 : minikube Django with Redis and Celery
- Docker & Kubernetes 4 : Django with RDS via AWS Kops
- Docker & Kubernetes : Kops on AWS
- Docker & Kubernetes : Ingress controller on AWS with Kops
- Docker & Kubernetes : HashiCorp's Vault and Consul on minikube
- Docker & Kubernetes : HashiCorp's Vault and Consul - Auto-unseal using Transit Secrets Engine
- Docker & Kubernetes : Persistent Volumes & Persistent Volumes Claims - hostPath and annotations
- Docker & Kubernetes : Persistent Volumes - Dynamic volume provisioning
- Docker & Kubernetes : DaemonSet
- Docker & Kubernetes : Secrets
- Docker & Kubernetes : kubectl command
- Docker & Kubernetes : Assign a Kubernetes Pod to a particular node in a Kubernetes cluster
- Docker & Kubernetes : Configure a Pod to Use a ConfigMap
- AWS : EKS (Elastic Container Service for Kubernetes)
- Docker & Kubernetes : Run a React app in a minikube
- Docker & Kubernetes : Minikube install on AWS EC2
- Docker & Kubernetes : Cassandra with a StatefulSet
- Docker & Kubernetes : Terraform and AWS EKS
- Docker & Kubernetes : Pods and Service definitions
- Docker & Kubernetes : Service IP and the Service Type
- Docker & Kubernetes : Kubernetes DNS with Pods and Services
- Docker & Kubernetes : Headless service and discovering pods
- Docker & Kubernetes : Scaling and Updating application
- Docker & Kubernetes : Horizontal pod autoscaler on minikubes
- Docker & Kubernetes : From a monolithic app to micro services on GCP Kubernetes
- Docker & Kubernetes : Rolling updates
- Docker & Kubernetes : Deployments to GKE (Rolling update, Canary and Blue-green deployments)
- Docker & Kubernetes : Slack Chat Bot with NodeJS on GCP Kubernetes
- Docker & Kubernetes : Continuous Delivery with Jenkins Multibranch Pipeline for Dev, Canary, and Production Environments on GCP Kubernetes
- Docker & Kubernetes : NodePort vs LoadBalancer vs Ingress
- Docker & Kubernetes : MongoDB / MongoExpress on Minikube
- Docker & Kubernetes : Load Testing with Locust on GCP Kubernetes
- Docker & Kubernetes : MongoDB with StatefulSets on GCP Kubernetes Engine
- Docker & Kubernetes : Nginx Ingress Controller on Minikube
- Docker & Kubernetes : Setting up Ingress with NGINX Controller on Minikube (Mac)
- Docker & Kubernetes : Nginx Ingress Controller for Dashboard service on Minikube
- Docker & Kubernetes : Nginx Ingress Controller on GCP Kubernetes
- Docker & Kubernetes : Kubernetes Ingress with AWS ALB Ingress Controller in EKS
- Docker & Kubernetes : Setting up a private cluster on GCP Kubernetes
- Docker & Kubernetes : Kubernetes Namespaces (default, kube-public, kube-system) and switching namespaces (kubens)
- Docker & Kubernetes : StatefulSets on minikube
- Docker & Kubernetes : RBAC
- Docker & Kubernetes Service Account, RBAC, and IAM
- Docker & Kubernetes - Kubernetes Service Account, RBAC, IAM with EKS ALB, Part 1
- Docker & Kubernetes : Helm Chart
- Docker & Kubernetes : My first Helm deploy
- Docker & Kubernetes : Readiness and Liveness Probes
- Docker & Kubernetes : Helm chart repository with Github pages
- Docker & Kubernetes : Deploying WordPress and MariaDB with Ingress to Minikube using Helm Chart
- Docker & Kubernetes : Deploying WordPress and MariaDB to AWS using Helm 2 Chart
- Docker & Kubernetes : Deploying WordPress and MariaDB to AWS using Helm 3 Chart
- Docker & Kubernetes : Helm Chart for Node/Express and MySQL with Ingress
- Docker & Kubernetes : Deploy Prometheus and Grafana using Helm and Prometheus Operator - Monitoring Kubernetes node resources out of the box
- Docker & Kubernetes : Deploy Prometheus and Grafana using kube-prometheus-stack Helm Chart
- Docker & Kubernetes : Istio (service mesh) sidecar proxy on GCP Kubernetes
- Docker & Kubernetes : Istio on EKS
- Docker & Kubernetes : Istio on Minikube with AWS EC2 for Bookinfo Application
- Docker & Kubernetes : Deploying .NET Core app to Kubernetes Engine and configuring its traffic managed by Istio (Part I)
- Docker & Kubernetes : Deploying .NET Core app to Kubernetes Engine and configuring its traffic managed by Istio (Part II - Prometheus, Grafana, pin a service, split traffic, and inject faults)
- Docker & Kubernetes : Helm Package Manager with MySQL on GCP Kubernetes Engine
- Docker & Kubernetes : Deploying Memcached on Kubernetes Engine
- Docker & Kubernetes : EKS Control Plane (API server) Metrics with Prometheus
- Docker & Kubernetes : Spinnaker on EKS with Halyard
- Docker & Kubernetes : Continuous Delivery Pipelines with Spinnaker and Kubernetes Engine
- Docker & Kubernetes : Multi-node Local Kubernetes cluster : Kubeadm-dind (docker-in-docker)
- Docker & Kubernetes : Multi-node Local Kubernetes cluster : Kubeadm-kind (k8s-in-docker)
- Docker & Kubernetes : nodeSelector, nodeAffinity, taints/tolerations, pod affinity and anti-affinity - Assigning Pods to Nodes
- Docker & Kubernetes : Jenkins-X on EKS
- Docker & Kubernetes : ArgoCD App of Apps with Heml on Kubernetes
- Docker & Kubernetes : ArgoCD on Kubernetes cluster
- Docker & Kubernetes : GitOps with ArgoCD for Continuous Delivery to Kubernetes clusters (minikube) - guestbook
Ph.D. / Golden Gate Ave, San Francisco / Seoul National Univ / Carnegie Mellon / UC Berkeley / DevOps / Deep Learning / Visualization