One place for hosting & domains

      December 2018

      How To Build a Node.js Application with Docker


      Introduction

      The Docker platform allows developers to package and run applications as containers. A container is an isolated process that runs on a shared operating system, offering a lighter weight alternative to virtual machines. Though containers are not new, they offer benefits — including process isolation and environment standardization — that are growing in importance as more developers use distributed application architectures.

      When building and scaling an application with Docker, the starting point is typically creating an image for your application, which you can then run in a container. The image includes your application code, libraries, configuration files, environment variables, and runtime. Using an image ensures that the environment in your container is standardized and contains only what is necessary to build and run your application.

      In this tutorial, you will create an application image for a static website that uses the Express framework and Bootstrap. You will then build a container using that image and push it to Docker Hub for future use. Finally, you will pull the stored image from your Docker Hub repository and build another container, demonstrating how you can recreate and scale your application.

      Prerequisites

      To follow this tutorial, you will need:

      Step 1 — Installing Your Application Dependencies

      To create your image, you will first need to make your application files, which you can then copy to your container. These files will include your application’s static content, code, and dependencies.

      First, create a directory for your project in your non-root user’s home directory. We will call ours node_project, but you should feel free to replace this with something else:

      Navigate to this directory:

      This will be the root directory of the project.

      Next, create a package.json file with your project's dependencies and other identifying information. Open the file with nano or your favorite editor:

      Add the following information about the project, including its name, author, license, entrypoint, and dependencies. Be sure to replace the author information with your own name and contact details:

      ~/node_project/package.json

      {
        "name": "nodejs-image-demo",
        "version": "1.0.0",
        "description": "nodejs image demo",
        "author": "Sammy the Shark <sammy@example.com>",
        "license": "MIT",
        "main": "app.js",
        "scripts": {
          "start": "node app.js",
          "test": "echo "Error: no test specified" && exit 1"
        },
        "keywords": [
          "nodejs",
          "bootstrap",
          "express"
        ],
        "dependencies": {
          "express": "^4.16.4"
        }
      }
      

      This file includes the project name, author, and license under which it is being shared. Npm recommends making your project name short and descriptive, and avoiding duplicates in the npm registry. We've listed the MIT license in the license field, permitting the free use and distribution of the application code.

      Additionally, the file specifies:

      • "main": The entrypoint for the application, app.js. You will create this file next.
      • "scripts": The commands that will run when you use npm start to start your application.
      • "dependencies": The project dependencies — in this case, Express 4.16.4 or above.

      Though this file does not list a repository, you can add one by following these guidelines on adding a repository to your package.json file. This is a good addition if you are versioning your application.

      Save and close the file when you've finished making changes.

      To install your project's dependencies, run the following command:

      This will install the packages you've listed in your package.json file in your project directory.

      We can now move on to building the application files.

      Step 2 — Creating the Application Files

      We will create a website that offers users information about sharks. Our application will have a main entrypoint, app.js, and a views directory that will include the project's static assets. The landing page, index.html, will offer users some preliminary information and a link to a page with more detailed shark information, sharks.html. In the views directory, we will create both the landing page and sharks.html.

      First, open app.js in the main project directory to define the project's routes:

      The first part of the file will create the Express application and Router objects, and define the base directory, port, and host as variables:

      ~/node_project/app.js

      var express = require("express");
      var app = express();
      var router = express.Router();
      
      var path = __dirname + '/views/';
      const PORT = 8080;
      const HOST = '0.0.0.0';
      

      The require function loads the express module, which we then use to create the app and router objects. The router object will perform the routing function of the application, and as we define HTTP method routes we will add them to this object to define how our application will handle requests.

      This section of the file also sets a few variables, path, PORT, and HOST:

      • path: Defines the base directory, which will be the views subdirectory within the current project directory.
      • HOST: Defines the address that the application will bind to and listen on. Setting this to 0.0.0.0 or all IPv4 addresses corresponds with Docker's default behavior of exposing containers to 0.0.0.0 unless otherwise instructed.
      • PORT: Tells the app to listen on and bind to port 8080.

      Next, set the routes for the application using the router object:

      ~/node_project/app.js

      ...
      
      router.use(function (req,res,next) {
        console.log("/" + req.method);
        next();
      });
      
      router.get("/",function(req,res){
        res.sendFile(path + "index.html");
      });
      
      router.get("/sharks",function(req,res){
        res.sendFile(path + "sharks.html");
      });
      

      The router.use function loads a middleware function that will log the router's requests and pass them on to the application's routes. These are defined in the subsequent functions, which specify that a GET request to the base project URL should return the index.html page, while a GET request to the /sharks route should return sharks.html.

      Finally, mount the router middleware and the application's static assets and tell the app to listen on port 8080:

      ~/node_project/app.js

      ...
      
      app.use(express.static(path));
      app.use("/", router);
      
      app.listen(8080, function () {
        console.log('Example app listening on port 8080!')
      })
      

      The finished app.js file will look like this:

      ~/node_project/app.js

      var express = require("express");
      var app = express();
      var router = express.Router();
      
      var path = __dirname + '/views/';
      const PORT = 8080;
      const HOST = '0.0.0.0';
      
      router.use(function (req,res,next) {
        console.log("/" + req.method);
        next();
      });
      
      router.get("/",function(req,res){
        res.sendFile(path + "index.html");
      });
      
      router.get("/sharks",function(req,res){
        res.sendFile(path + "sharks.html");
      });
      
      app.use(express.static(path));
      app.use("/", router);
      
      app.listen(8080, function () {
        console.log('Example app listening on port 8080!')
      })
      

      Save and close the file when you are finished.

      Next, let's add some static content to the application. Start by creating the views directory:

      Open the landing page file, index.html:

      Add the following code to the file, which will import Boostrap and create a jumbotron component with a link to the more detailed sharks.html info page:

      ~/node_project/views/index.html

      <!DOCTYPE html>
      <html lang="en">
         <head>
            <title>About Sharks</title>
            <meta charset="utf-8">
            <meta name="viewport" content="width=device-width, initial-scale=1">
            <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
            <link href="css/styles.css" rel="stylesheet">
            <link href='https://fonts.googleapis.com/css?family=Merriweather:400,700' rel='stylesheet' type='text/css'>
            <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
            <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
         </head>
         <body>
            <nav class="navbar navbar-inverse navbar-static-top">
               <div class="container">
                  <div class="navbar-header">
                     <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1" aria-expanded="false">
                     <span class="sr-only">Toggle navigation</span>
                     <span class="icon-bar"></span>
                     <span class="icon-bar"></span>
                     <span class="icon-bar"></span>
                     </button>
                     <a class="navbar-brand" href="#">Everything Sharks</a>
                  </div>
                  <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
                     <ul class="nav navbar-nav mr-auto">
                        <li class="active"><a href="/">Home</a></li>
                        <li><a href="http://www.digitalocean.com/sharks">Sharks</a></li>
                     </ul>
                  </div>
               </div>
            </nav>
            <div class="jumbotron">
               <div class="container">
                  <h1>Want to Learn About Sharks?</h1>
                  <p>Are you ready to learn about sharks?</p>
                  <br>
                  <p><a class="btn btn-primary btn-lg" href="http://www.digitalocean.com/sharks" role="button">Get Shark Info</a></p>
               </div>
            </div>
            <div class="container">
               <div class="row">
                  <div class="col-md-6">
                     <h3>Not all sharks are alike</h3>
                     <p>Though some are dangerous, sharks generally do not attack humans. Out of the 500 species known to researchers, only 30 have been known to attack humans.</p>
                  </div>
                  <div class="col-md-6">
                     <h3>Sharks are ancient</h3>
                     <p>There is evidence to suggest that sharks lived up to 400 million years ago.</p>
                  </div>
               </div>
            </div>
         </body>
      </html>
      

      The top-level navbar here allows users to toggle between the Home and Sharks pages. In the navbar-nav subcomponent, we are using Bootstrap's active class to indicate the current page to the user. We've also specified the routes to our static pages, which match the routes we defined in app.js:

      ~/node_project/views/index.html

      ...
      <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
          <ul class="nav navbar-nav mr-auto">
              <li class="active"><a href="/">Home</a></li>
              <li><a href="http://www.digitalocean.com/sharks">Sharks</a></li>
          </ul>
      </div>
      ...
      

      Additionally, we've created a link to our shark information page in our jumbotron's button:

      ~/node_project/views/index.html

      ...
      <div class="jumbotron">
          <div class="container">
            <h1>Want to Learn About Sharks?</h1>
            <p>Are you ready to learn about sharks?</p>
            <br>
            <p><a class="btn btn-primary btn-lg" href="http://www.digitalocean.com/sharks" role="button">Get Shark Info</a></p>
          </div>
      </div>
      ...
      

      There is also a link to a custom style sheet in the header:

      ~/node_project/views/index.html

      ...
      <link href="css/styles.css" rel="stylesheet">
      ...
      

      We will create this style sheet at the end of this step.

      Save and close the file when you are finished.

      With the application landing page in place, we can create our shark information page, sharks.html, which will offer interested users more information about sharks.

      Open the file:

      Add the following code, which imports Bootstrap and the custom style sheet and offers users detailed information about certain sharks:

      ~/node_project/views/sharks.html

      <!DOCTYPE html>
      <html lang="en">
         <head>
            <title>About Sharks</title>
            <meta charset="utf-8">
            <meta name="viewport" content="width=device-width, initial-scale=1">
            <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
            <link href="css/styles.css" rel="stylesheet">
            <link href='https://fonts.googleapis.com/css?family=Merriweather:400,700' rel='stylesheet' type='text/css'>
            <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
            <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
         </head>
         <nav class="navbar navbar-inverse navbar-static-top">
            <div class="container">
               <div class="navbar-header">
                  <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1" aria-expanded="false">
                  <span class="sr-only">Toggle navigation</span>
                  <span class="icon-bar"></span>
                  <span class="icon-bar"></span>
                  <span class="icon-bar"></span>
                  </button>
                  <a class="navbar-brand" href="/">Everything Sharks</a>
               </div>
               <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
                  <ul class="nav navbar-nav mr-auto">
                     <li><a href="/">Home</a></li>
                     <li class="active"><a href="http://www.digitalocean.com/sharks">Sharks</a></li>
                  </ul>
               </div>
            </div>
         </nav>
         <div class="jumbotron text-center">
            <h1>Shark Info</h1>
         </div>
         <div class="container">
            <div class="row">
               <div class="col-md-6">
                  <p>
                  <div class="caption">Some sharks are known to be dangerous to humans, though many more are not. The sawshark, for example, is not considered a threat to humans.</div>
                  <img src="https://assets.digitalocean.com/articles/docker_node_image/sawshark.jpg" alt="Sawshark">
                  </p>
               </div>
               <div class="col-md-6">
                  <p>
                  <div class="caption">Other sharks are known to be friendly and welcoming!</div>
                  <img src="https://assets.digitalocean.com/articles/docker_node_image/sammy.png" alt="Sammy the Shark">
                  </p>
               </div>
            </div>
          </div>
         </body>
      </html>
      

      Note that in this file, we again use the active class to indicate the current page.

      Save and close the file when you are finished.

      Finally, create the custom CSS style sheet that you've linked to in index.html and sharks.html by first creating a css folder in the views directory:

      Open the style sheet:

      • nano views/css/styles.css

      Add the following code, which will set the desired color and font for our pages:

      ~/node_project/views/css/styles.css

      .navbar {
          margin-bottom: 0;
      }
      
      body {
          background: #020A1B;
          color: #ffffff;
          font-family: 'Merriweather', sans-serif;
      }
      
      h1,
      h2 {
          font-weight: bold;
      }
      
      p {
          font-size: 16px;
          color: #ffffff;
      }
      
      .jumbotron {
          background: #0048CD;
          color: white;
          text-align: center;
      }
      
      .jumbotron p {
          color: white;
          font-size: 26px;
      }
      
      .btn-primary {
          color: #fff;
          text-color: #000000;
          border-color: white;
          margin-bottom: 5px;
      }
      
      img,
      video,
      audio {
          margin-top: 20px;
          max-width: 80%;
      }
      
      div.caption: {
          float: left;
          clear: both;
      }
      

      In addition to setting font and color, this file also limits the size of the images by specifying a max-width of 80%. This will prevent them from taking up more room than we would like on the page.

      Save and close the file when you are finished.

      With the application files in place and the project dependencies installed, you are ready to start the application.

      If you followed the initial server setup tutorial in the prerequisites, you will have an active firewall permitting only SSH traffic. To permit traffic to port 8080 run:

      To start the application, make sure that you are in your project's root directory:

      Start the application with npm start:

      Navigate your browser to http://your_server_ip:8080. You will see the following landing page:

      Application Landing Page

      Click on the Get Shark Info button. You will see the following information page:

      Shark Info Page

      You now have an application up and running. When you are ready, quit the server by typing CTRL+C. We can now move on to creating the Dockerfile that will allow us to recreate and scale this application as desired.

      Step 3 — Writing the Dockerfile

      Your Dockerfile specifies what will be included in your application container when it is executed. Using a Dockerfile allows you to define your container environment and avoid discrepancies with dependencies or runtime versions.

      Following these guidelines on building optimized containers, we will make our image as efficient as possible by minimizing the number of image layers and restricting the image's function to a single purpose — recreating our application files and static content.

      In your project's root directory, create the Dockerfile:

      Docker images are created using a succession of layered images that build on one another. Our first step will be to add the base image for our application that will form the starting point of the application build.

      Let's use the node:10 image, since, at the time of writing, this is the recommended LTS version of Node.js. Add the following FROM instruction to set the application's base image:

      ~/node_project/Dockerfile

      FROM node:10
      

      This image includes Node.js and npm. Each Dockerfile must begin with a FROM instruction.

      By default, the Docker Node image includes a non-root node user that you can use to avoid running your application container as root. It is a recommended security practice to avoid running containers as root and to restrict capabilities within the container to only those required to run its processes. We will therefore use the node user's home directory as the working directory for our application and set them as our user inside the container. For more information about best practices when working with the Docker Node image, see this best practices guide.

      To fine-tune the permissions on our application code in the container, let's create the node_modules subdirectory in /home/node along with the app directory. Creating these directories will ensure that they have the permissions we want, which will be important when we create local node modules in the container with npm install. In addition to creating these directories, we will set ownership on them to our node user:

      ~/node_project/Dockerfile

      ...
      RUN mkdir -p /home/node/app/node_modules && chown -R node:node /home/node/app
      

      For more information on the utility of consolidating RUN instructions, see this discussion of how to manage container layers.

      Next, set the working directory of the application to /home/node/app:

      ~/node_project/Dockerfile

      ...
      WORKDIR /home/node/app
      

      If a WORKDIR isn't set, Docker will create one by default, so it's a good idea to set it explicitly.

      Next, copy the package.json and package-lock.json (for npm 5+) files:

      ~/node_project/Dockerfile

      ...
      COPY package*.json ./
      

      Adding this COPY instruction before running npm install or copying the application code allows us to take advantage of Docker's caching mechanism. At each stage in the build, Docker will check to see if it has a layer cached for that particular instruction. If we change package.json, this layer will be rebuilt, but if we don't, this instruction will allow Docker to use the existing image layer and skip reinstalling our node modules.

      After copying the project dependencies, we can run npm install:

      ~/node_project/Dockerfile

      ...
      RUN npm install
      

      Copy your application code to the working application directory on the container:

      ~/node_project/Dockerfile

      ...
      COPY . .
      

      To ensure that the application files are owned by the non-root node user, copy the permissions from your application directory to the directory on the container:

      ~/node_project/Dockerfile

      ...
      COPY --chown=node:node . .
      

      Set the user to node:

      ~/node_project/Dockerfile

      ...
      USER node
      

      Expose port 8080 on the container and start the application:

      ~/node_project/Dockerfile

      ...
      EXPOSE 8080
      
      CMD [ "npm", "start" ]
      

      EXPOSE does not publish the port, but instead functions as a way of documenting which ports on the container will be published at runtime. CMD runs the command to start the application — in this case, npm start. Note that there should only be one CMD instruction in each Dockerfile. If you include more than one, only the last will take effect.

      There are many things you can do with the Dockerfile. For a complete list of instructions, please refer to Docker's Dockerfile reference documentation.

      The complete Dockerfile looks like this:

      ~/node_project/Dockerfile

      
      FROM node:10
      
      RUN mkdir -p /home/node/app/node_modules && chown -R node:node /home/node/app
      
      WORKDIR /home/node/app
      
      COPY package*.json ./
      
      RUN npm install
      
      COPY . .
      
      COPY --chown=node:node . .
      
      USER node
      
      EXPOSE 8080
      
      CMD [ "npm", "start" ]
      

      Save and close the file when you are finished editing.

      Before building the application image, let's add a .dockerignore file. Working in a similar way to a .gitignore file, .dockerignore specifies which files and directories in your project directory should not be copied over to your container.

      Open the .dockerignore file:

      Inside the file, add your local node modules, npm logs, Dockerfile, and .dockerignore file:

      ~/node_project/.dockerignore

      node_modules
      npm-debug.log
      Dockerfile
      .dockerignore
      

      If you are working with Git then you will also want to add your .git directory and .gitignore file.

      Save and close the file when you are finished.

      You are now ready to build the application image using the docker build command. Using the -t flag with docker build will allow you to tag the image with a memorable name. Because we are going to push the image to Docker Hub, let's include our Docker Hub username in the tag. We will tag the image as nodejs-image-demo, but feel free to replace this with a name of your own choosing. Remember to also replace your_dockerhub_username with your own Docker Hub username:

      • docker build -t your_dockerhub_username/nodejs-image-demo .

      The . specifies that the build context is the current directory.

      It will take a minute or two to build the image. Once it is complete, check your images:

      You will see the following output:

      Output

      REPOSITORY TAG IMAGE ID CREATED SIZE your_dockerhub_username/nodejs-image-demo latest 1c723fb2ef12 8 seconds ago 895MB node 10 f09e7c96b6de 17 hours ago 893MB

      It is now possible to create a container with this image using docker run. We will include three flags with this command:

      • -p: This publishes the port on the container and maps it to a port on our host. We will use port 80 on the host, but you should feel free to modify this as necessary if you have another process running on that port. For more information about how this works, see this discussion in the Docker docs on port binding.
      • -d: This runs the container in the background.
      • --name: This allows us to give the container a memorable name.

      Run the following command to build the container:

      • docker run --name nodejs-image-demo -p 80:8080 -d your_dockerhub_username/nodejs-image-demo

      Once your container is up and running, you can inspect a list of your running containers with docker ps:

      You will see the following output:

      Output

      CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES e50ad27074a7 your_dockerhub_username/nodejs-image-demo "npm start" 8 seconds ago Up 7 seconds 0.0.0.0:80->8080/tcp nodejs-image-demo

      With your container running, you can now visit your application by navigating your browser to http://your_server_ip. You will see your application landing page once again:

      Application Landing Page

      Now that you have created an image for your application, you can push it to Docker Hub for future use.

      Step 4 — Using a Repository to Work with Images

      By pushing your application image to a registry like Docker Hub, you make it available for subsequent use as you build and scale your containers. We will demonstrate how this works by pushing the application image to a repository and then using the image to recreate our container.

      The first step to pushing the image is to log in to the Docker Hub account you created in the prerequisites:

      • docker login -u your_dockerhub_username -p your_dockerhub_password

      Logging in this way will create a ~/.docker/config.json file in your user's home directory with your Docker Hub credentials.

      You can now push the application image to Docker Hub using the tag you created earlier, your_dockerhub_username/nodejs-image-demo:

      • docker push your_dockerhub_username/nodejs-image-demo

      Let's test the utility of the image registry by destroying our current application container and image and rebuilding them with the image in our repository.

      First, list your running containers:

      You will see the following output:

      Output

      CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES e50ad27074a7 your_dockerhub_username/nodejs-image-demo "npm start" 3 minutes ago Up 3 minutes 0.0.0.0:80->8080/tcp nodejs-image-demo

      Using the CONTAINER ID listed in your output, stop the running application container. Be sure to replace the highlighted ID below with your own CONTAINER ID:

      List your all of your images with the -a flag:

      You will see the following output with the name of your image, your_dockerhub_username/nodejs-image-demo, along with the node image and the other images from your build:

      Output

      REPOSITORY TAG IMAGE ID CREATED SIZE your_dockerhub_username/nodejs-image-demo latest 1c723fb2ef12 7 minutes ago 895MB <none> <none> e039d1b9a6a0 7 minutes ago 895MB <none> <none> dfa98908c5d1 7 minutes ago 895MB <none> <none> b9a714435a86 7 minutes ago 895MB <none> <none> 51de3ed7e944 7 minutes ago 895MB <none> <none> 5228d6c3b480 7 minutes ago 895MB <none> <none> 833b622e5492 8 minutes ago 893MB <none> <none> 5c47cc4725f1 8 minutes ago 893MB <none> <none> 5386324d89fb 8 minutes ago 893MB <none> <none> 631661025e2d 8 minutes ago 893MB node 10 f09e7c96b6de 17 hours ago 893MB

      Remove the stopped container and all of the images, including unused or dangling images, with the following command:

      Type y when prompted in the output to confirm that you would like to remove the stopped container and images. Be advised that this will also remove your build cache.

      You have now removed both the container running your application image and the image itself. For more information on removing Docker containers, images, and volumes, please see How To Remove Docker Images, Containers, and Volumes.

      With all of your images and containers deleted, you can now pull the application image from Docker Hub:

      • docker pull your_dockerhub_username/nodejs-image-demo

      List your images once again:

      You will see your application image:

      Output

      REPOSITORY TAG IMAGE ID CREATED SIZE your_dockerhub_username/nodejs-image-demo latest 1c723fb2ef12 11 minutes ago 895MB

      You can now rebuild your container using the command from Step 3:

      • docker run --name nodejs-image-demo -p 80:8080 -d your_dockerhub_username/nodejs-image-demo

      List your running containers:

      Output

      CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES f6bc2f50dff6 your_dockerhub_username/nodejs-image-demo "npm start" 4 seconds ago Up 3 seconds 0.0.0.0:80->8080/tcp nodejs-image-demo

      Visit http://your_server_ip once again to view your running application.

      Conclusion

      In this tutorial you created a static web application with Express and Bootstrap, as well as a Docker image for this application. You used this image to create a container and pushed the image to Docker Hub. From there, you were able to destroy your image and container and recreate them using your Docker Hub repository.

      If you are interested in learning more about how to work with tools like Docker Compose and Docker Machine to create multi-container setups, you can look at the following guides:

      For general tips on working with container data, see:

      If you are interested in other Docker-related topics, please see our complete library of Docker tutorials.



      Source link

      How To Troubleshoot Issues in MySQL


      Introduction

      MySQL is an open-source relational database management system (RDBMS), the most popular of its kind in the world. As is the case when working with any software, both newcomers and experienced users can run into confusing error messages or difficult-to-diagnose problems.

      This guide will serve as a troubleshooting resource and starting point as you diagnose your MySQL setup. We’ll go over some of the issues that many MySQL users encounter and provide guidance for troubleshooting specific problems. We will also include links to DigitalOcean tutorials and the official MySQL documentation that may be useful in certain cases.

      Please note that this guide assumes the setup described in How To Install MySQL on Ubuntu 18.04, and the linked tutorials throughout the guide reflect this configuration. If your server is running another distribution, however, you can find a guide specific to that distro in the Tutorial Version Menu at the top of the linked tutorials when one is available.

      How To Get Started with MySQL

      The place where many first-time users of MySQL run into a problem is during the installation and configuration process. Our guide on How To Install MySQL on Ubuntu 18.04 provides instructions on how to set up a basic configuration and may be helpful to those new to MySQL.

      Another reason some users run into issues is that their application requires database features that are only present in the latest releases, but the version of MySQL available in the default repositories of some Linux distributions — including Ubuntu — isn’t the latest version. For this reason, the MySQL developers maintain their own software repository, which you can use to install the latest version and keep it up to date. Our tutorial “How To Install the Latest MySQL on Ubuntu 18.04” provides instructions on how to do this.

      How to Access MySQL Error Logs

      Oftentimes, the root cause of slowdowns, crashes, or other unexpected behavior in MySQL can be determined by analyzing its error logs. On Ubuntu systems, the default location for the MySQL is /var/log/mysql/error.log. In many cases, the error logs are most easily read with the less program, a command line utility that allows you to view files but not edit them:

      • sudo less /var/log/mysql/error.log

      If MySQL isn’t behaving as expected, you can obtain more information about the source of the trouble by running this command and diagnosing the error based on the log’s contents.

      Resetting the root MySQL User’s Password

      If you’ve set a password for your MySQL installation’s root user but have since forgotten it, you could be locked out of your databases. As long as you have access to the server on which your database is hosted, though, you should be able to reset it.

      This process differs from resetting the password for a standard Linux username. Check out our guide on How To Reset Your MySQL or MariaDB Root Password to walk through and understand this process.

      Troubles with Queries

      Sometimes users run into problems once they begin issuing queries on their data. In some database systems, including MySQL, query statements in must end in a semicolon (;) for the query to complete, as in the following example:

      If you fail to include a semicolon at the end of your query, the prompt will continue on a new line until you complete the query by entering a semicolon and pressing ENTER.

      Some users may find that their queries are exceedingly slow. One way to find which query statement is the cause of a slowdown is to enable and view MySQL's slow query log. To do this, open your mysqld.cnf file, which is used to configure options for the MySQL server. This file is typically stored within the /etc/mysql/mysql.conf.d/ directory:

      • sudo nano /etc/mysql/mysql.conf.d/mysqld.cnf

      Scroll through the file until you see the following lines:

      /etc/mysql/mysql.conf.d/mysqld.cnf

      . . .
      #slow_query_log         = 1
      #slow_query_log_file    = /var/log/mysql/mysql-slow.log
      #long_query_time = 2
      #log-queries-not-using-indexes
      . . .
      

      These commented-out directives provide MySQL's default configuration options for the slow query log. Specifically, here's what each of them do:

      • slow-query-log: Setting this to 1 enables the slow query log.
      • slow-query-log-file: This defines the file where MySQL will log any slow queries. In this case, it points to the /var/log/mysql-slow.log file.
      • long_query_time: By setting this directive to 2, it configures MySQL to log any queries that take longer than 2 seconds to complete.
      • log_queries_not_using_indexes: This tells MySQL to also log any queries that run without indexes to the /var/log/mysql-slow.log file. This setting isn't required for the slow query log to function, but it can be helpful for spotting inefficient queries.

      Uncomment each of these lines by removing the leading pound signs (#). The section will now look like this:

      /etc/mysql/mysql.conf.d/mysqld.cnf

      . . .
      slow_query_log = 1
      slow_query_log_file = /var/log/mysql-slow.log
      long_query_time = 2
      log_queries_not_using_indexes
      . . .
      

      Note: If you're running MySQL 8+, these commented lines will not be in the mysqld.cnf file by default. In this case, add the following lines to the bottom of the file:

      /etc/mysql/mysql.conf.d/mysqld.cnf

      . . .
      slow_query_log = 1
      slow_query_log_file = /var/log/mysql-slow.log
      long_query_time = 2
      log_queries_not_using_indexes
      

      After enabling the slow query log, save and close the file. Then restart the MySQL service:

      • sudo systemctl restart mysql

      With these settings in place, you can find problematic query statements by viewing the slow query log. You can do so with less, like this:

      • sudo less /var/log/mysql_slow.log

      Once you've singled out the queries causing the slowdown, you may find our guide on How To Optimize Queries and Tables in MySQL and MariaDB on a VPS to be helpful with optimizing them.

      Additionally, MySQL includes the EXPLAIN statement, which provides information about how MySQL executes queries. This page from the official MySQL documentation provides insight on how to use EXPLAIN to highlight inefficient queries.

      For help with understanding basic query structures, see our Introduction to MySQL Queries.

      Allowing Remote Access

      Many websites and applications start off with their web server and database backend hosted on the same machine. With time, though, a setup like this can become cumbersome and difficult to scale. A common solution is to separate these functions by setting up a remote database, allowing the server and database to grow at their own pace on their own machines.

      One of the more common problems that users run into when trying to set up a remote MySQL database is that their MySQL instance is only configured to listen for local connections. This is MySQL's default setting, but it won't work for a remote database setup since MySQL must be able to listen for an external IP address where the server can be reached. To enable this, open up your mysqld.cnf file:

      • sudo nano /etc/mysql/mysql.conf.d/mysqld.cnf

      Navigate to the line that begins with the bind-address directive. It will look like this:

      /etc/mysql/mysql.conf.d/mysqld.cnf

      . . .
      lc-messages-dir = /usr/share/mysql
      skip-external-locking
      #
      # Instead of skip-networking the default is now to listen only on
      # localhost which is more compatible and is not less secure.
      bind-address            = 127.0.0.1
      . . .
      

      By default, this value is set to 127.0.0.1, meaning that the server will only look for local connections. You will need to change this directive to reference an external IP address. For the purposes of troubleshooting, you could set this directive to a wildcard IP address, either *, ::, or 0.0.0.0:

      /etc/mysql/mysql.conf.d/mysqld.cnf

      . . .
      lc-messages-dir = /usr/share/mysql
      skip-external-locking
      #
      # Instead of skip-networking the default is now to listen only on
      # localhost which is more compatible and is not less secure.
      bind-address            = 0.0.0.0
      . . .
      

      Note: If you're running MySQL 8+, the bind-address directive will not be in the mysqld.cnf file by default. In this case, add the following highlighted line to the bottom of the file:

      /etc/mysql/mysql.conf.d/mysqld.cnf

      . . .
      [mysqld]
      pid-file        = /var/run/mysqld/mysqld.pid
      socket          = /var/run/mysqld/mysqld.sock
      datadir         = /var/lib/mysql
      log-error       = /var/log/mysql/error.log
      bind-address            = 0.0.0.0
      

      After changing this line, save and close the file and then restart the MySQL service:

      • sudo systemctl restart mysql

      Following this, try accessing your database remotely from another machine:

      • mysql -u user -h database_server_ip -p

      If you're able to access your database, it confirms that the bind-address directive in your configuration file was the issue. Please note, though, that setting bind-address to 0.0.0.0 is insecure as it allows connections to your server from any IP address. On the other hand, if you're still unable to access the database remotely, then something else may be causing the issue. In either case, you may find it helpful to follow our guide on How To Set Up a Remote Database to Optimize Site Performance with MySQL on Ubuntu 18.04 to set up a more secure remote database configuration.

      MySQL Stops Unexpectedly or Fails to Start

      The most common cause of crashes in MySQL is that it stopped or failed to start due to insufficient memory. To check this, you will need to review the MySQL error log after a crash.

      First, attempt to start the MySQL server by typing:

      • sudo systemctl start mysql

      Then review the error logs to see what's causing MySQL to crash. You can use less to review your logs, one page at a time:

      • sudo less /var/log/mysql/error.log

      Some common messages that would indicate an insufficient amount of memory are Out of memory or mmap can't allocate.

      Potential solutions to an inadequate amount of memory are:

      • Optimizing your MySQL configuration. A great open-source tool for this is MySQLtuner. Running the MySQLtuner script will output a set of recommended adjustments to your MySQL configuration file (mysqld.cnf). Note that the longer your server has been running before using MySQLTuner, the more accurate its suggestions will be. To get a memory usage estimate of both your current settings and those proposed by MySQLTimer, use this MySQL Calculator.

      • Reducing your web application’s reliance on MySQL for page loads. This can usually be done by adding static caching to your application. Examples for this include Joomla, which has caching as a built-in feature that can be enabled, and WP Super Cache, a WordPress plugin that adds this kind of functionality.

      • Upgrading to a larger VPS. At minimum, we recommend a server with at least 1GB of RAM for any server using a MySQL database, but the size and type of your data can significantly affect memory requirements.

      Take note that even though upgrading your server is a potential solution, it's only recommended after you investigate and weigh all of your other options. An upgraded server with more resources will likewise cost more money, so you should only go through with resizing if it truly ends up being your best option. Also note that the MySQL documentation includes a number of other suggestions for diagnosing and preventing crashes.

      Corrupted Tables

      Occasionally, MySQL tables can become corrupted, meaning that an error has occurred and the data held within them is unreadable. Attempts to read from a corrupted table will usually lead to the server crashing.

      Some common causes of corrupted tables are:

      • The MySQL server stops in middle of a write.
      • An external program modifies a table that's simultaneously being modified by the server.
      • The machine is shut down unexpectedly.
      • The computer hardware fails.
      • There's a software bug somewhere in the MySQL code.

      If you suspect that one of your tables has been corrupted, you should make a backup of your data directory before troubleshooting or attempting to fix the table. This will help to minimize the risk of data loss.

      First, stop the MySQL service:

      • sudo systemctl stop mysql

      Then copy all of your data into a new backup directory. On Ubuntu systems, the default data directory is /var/lib/mysql/:

      • cp -r /var/lib/mysql /var/lib/mysql_bkp

      After making the backup, you're ready to begin investigating whther the table is in fact corrupted. If the table uses the MyISAM storage engine, you can check whether it's corrupted by running a CHECK TABLE statement from the MySQL prompt:

      A message will appear in this statement's output letting you know whether or not it's corrupted. If the MyISAM table is indeed corrupted, it can usually be repaired by issuing a REPAIR TABLE statement:

      Assuming the repair was successful, you will see a message like the following in your output:

      Output

      +--------------------------+--------+----------+----------+ | Table | Op | Msg_type | Msg_text | +--------------------------+--------+----------+----------+ | database_name.table_name | repair | status | OK | +--------------------------+--------+----------+----------+

      If the table is still corrupted, though, the MySQL documentation suggests a few alternative methods for repairing corrupted tables.

      On the other hand, if the corrupted table uses the InnoDB storage engine, then the process for repairing it will be different. InnoDB is the default storage engine in MySQL as of version 5.5, and it features automated corruption checking and repair operations. InnoDB checks for corrupted pages by performing checksums on every page it reads, and if it finds a checksum discrepancy it will automatically stop the MySQL server.

      There is rarely a need to repair InnoDB tables, as InnoDB features a crash recovery mechanism that can resolve most issues when the server is restarted. However, if you do encounter a situation where you need to rebuild a corrupted InnoDB table, the MySQL documentation recommends using the "Dump and Reload" method. This involves regaining access to the corrupted table, using the mysqldump utility to create a logical backup of the table, which will retain the table structure and the data within it, and then reloading the table back into the database.

      With that in mind, try restarting the MySQL service to see if doing so will allow you access to the server:

      • sudo systemctl restart mysql

      If the server remains crashed or otherwise inaccessible, then it may be helpful to enable InnoDB's force_recovery option. You can do this by editing the mysqld.cnf file:

      • sudo nano /etc/mysql/mysql.conf.d/mysqld.cnf

      In the [mysqld] section, add the following line:

      /etc/mysql/mysql.conf.d/mysqld.cnf

      . . .
      [mysqld]
      . . .
      innodb_force_recovery=1
      

      Save and close the file, and then try restarting the MySQL service again. If you can successfully access the corrupted table, use the mysqldump utility to dump your table data to a new file. You can name this file whatever you like, but here we'll name it out.sql:

      • mysqldump database_name table_name > out.sql

      Then drop the table from the database. To avoid having to reopen the MySQL prompt, you can use the following syntax:

      • mysql -u user -p --execute="DROP TABLE database_name.table_name"

      Following this, restore the table with the dump file you just created:

      • mysql -u user -p < out.sql

      Note that the InnoDB storage engine is generally more fault-tolerant than the older MyISAM engine. Tables using InnoDB can still be corrupted, but because of its auto-recovery features the risk of table corruption and crashes is decidedly lower.

      Socket Errors

      MySQL manages connections to the database server through the use of a socket file, a special kind of file that facilitates communications between different processes. The MySQL server's socket file is named mysqld.sock and on Ubuntu systems it's usually stored in the /var/run/mysqld/ directory. This file is created by the MySQL service automatically.

      Sometimes, changes to your system or your MySQL configuration can result in MySQL being unable to read the socket file, preventing you from gaining access to your databases. The most common socket error looks like this:

      Output

      ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/var/run/mysqld/mysqld.sock' (2)

      There are a few reasons why this error may occur, and a few potential ways to resolve it.

      One common cause of this error is that the MySQL service is stopped or did not start to begin with, meaning that it was unable to create the socket file in the first place. To find out if this is the reason you're seeing this error, try starting the service with systemctl:

      • sudo systemctl start mysql

      Then try accessing the MySQL prompt again. If you still receive the socket error, double check the location where your MySQL installation is looking for the socket file. This information can be found in the mysqld.cnf file:

      • sudo nano /etc/mysql/mysql.conf.d/mysql.cnf

      Look for the socket parameter in the [mysqld] section of this file. It will look like this:

      /etc/mysql/mysql.conf.d/mysqld.cnf

      . . .
      [mysqld]
      user            = mysql
      pid-file        = /var/run/mysqld/mysqld.pid
      socket          = /var/run/mysqld/mysqld.sock
      port            = 3306
      . . .
      

      Close this file, then ensure that the mysqld.sock file exists by running an ls command on the directory where MySQL expects to find it:

      If the socket file exists, you will see it in this command's output:

      Output

      . .. mysqld.pid mysqld.sock mysqld.sock.lock

      If the file does not exist, the reason may be that MySQL is trying to create it, but does not have adequate permissions to do so. You can ensure that the correct permissions are in place by changing the directory's ownership to the mysql user and group:

      • sudo chown mysql:mysql /var/run/mysqld/

      Then ensure that the mysql user has the appropriate permissions over the directory. Setting these to 775 will work in most cases:

      • sudo chmod -R 755 /var/run/mysqld/

      Finally, restart the MySQL service so it can attempt to create the socket file again:

      • sudo systemctl restart mysql

      Then try accessing the MySQL prompt once again. If you still encounter the socket error, there's likely a deeper issue with your MySQL instance, in which case you should review the error log to see if it can provide any clues.

      Conclusion

      MySQL serves as the backbone of countless data-driven applications and websites. With so many use cases, there are as many potential causes of errors. Likewise, there are also many different ways to resolve such errors. We've covered some of the most frequently encountered errors in this guide, but there are many more that could come up depending on how your own application works with MySQL.

      If you weren't able to find a solution to your particular problem, we hope that this guide will at least give you some background into MySQL troubleshooting and help you find the source of your errors. For more information, you can look at the official MySQL documentation, which covers the topics we have discussed here as well as other troubleshooting strategies.

      Additionally, if your MySQL database is hosted on a DigitalOcean Droplet, you can contact our Support team for further assistance.



      Source link

      Make Your Website Merry and Bright with These 10 Holiday Marketing Ideas


      The bright and cheery season is finally here!

      String up the twinkling lights, bust out your ugliest sweater, and get to work decking out your website.

      via GIPHY

      Wait?

      Work during the holidays?!

      Yeah, I do sound like the Grinch right now. But getting festive for Festivus (and all the other major end-of-year holidays) can actually give your website more chances to unwrap extra visitors.

      If your cup of ideas isn’t running over, we’ve got you covered. Our gift to you? Ten great ways to freshen up your website for the holidays. Batteries not included.

      Before You Get Started

      Before you delve too deep in creating new holiday campaigns, take the time to look at the results of your holiday promotions from last year. Hopefully, you already did this when you were prepping your website for Black Friday and Cyber Monday. But if not, let’s refresh!

      Let Your Goals Guide

      First, take a moment to reflect. What are your company goals? And what do you need to get out of the holiday shopping season: more sales, leads, or subscribers? Every action you take, including fun holiday marketing campaigns, should drive toward those goals.

      If the campaign you’ve got in mind won’t help you achieve your goals, put that idea on the naughty list.

      Review Last Year

      Which promotions registered with customers last December? Which ones fell flat? Before you put fingers to keyboard, take a look at last year’s results and build from there.

      Plan Out Sales in Advance

      Run the numbers to find out what deals you can afford to offer during the holidays. Then use this information to help you choose which holidays ideas to implement on your website.

      Analyze Your Channels

      You need to know how you’re going to spread the word about your holiday campaigns and promotions. So ask yourself: Do you have an email subscriber list? How strong is your social media presence? Is one platform stronger than the others? Have you ever used PPC?

      Scout Out the Competition

      What have your competitors done for the holidays that you could tweak for your specific audience? Make a list. You can even look to big brands for ideas (lots of inspiration coming your way).

      Got all that? Okay, on to the ideas!

      10 Holiday Ideas to Brighten Up Your Website

      1. Make Sure Your Website is Ready for the Season

      First things first, let’s get technical to make sure your website is geared up and ready for the season.

      You can do this by checking with your hosting provider to plan for any surges in traffic. If you need to upgrade for more resources, do it before the holidays hit. That way, you won’t run into issues when all those visitors come knocking on your website’s door to get your holiday deals.

      Next, make sure your payment gateway can handle more transactions. You may also want to consider upgrading your services to accept more forms of payments and double check your security features. The gifts of convenience and security are the type of holiday cheer your customers will appreciate.

      Need a baller payment gateway for your website? Here are 10 can’t-miss options.

      Finally, optimize to reduce your site’s load times. I could give you a mile-long checklist for this, but you’re busy — I get it. Instead, try these ten speedy-site tips, and then test your site’s performance with Google’s PageSpeed Insights.

      Now, you’re ready to roll!

      2. Dress Your Website up for the Holidays

      Your customers are used to your website’s regular look, and that’s great — for most of the year. When the holidays roll around, though, consider giving your site a little extra sparkle.

      Take caffeine juggernaut Starbucks.

      Everyone is used to the company’s white-and-green siren, but come November 1, Starbucks’ cups get a little more festive.

      Obviously, your website isn’t a paper cup. So when it comes to zhuzhing up your homepage, a lot of jingle can go all the way. Let’s look at a brand that does holiday cheer well: Bath and Body Works.

      As soon as visitors hit the website, they are greeted with twinkling snowflakes and a giant, festive banner image. Even their promotion code is cheery: SNOWFALL.

      One word of warning (and good, old-fashioned marketing advice): know your audience.

      When you opt to make your branding more holiday-themed, pay attention to how your customers receive it. If you’re worried, solicit customer feedback, run some A/B tests, or hold a focus group.

      You don’t want to catch any flack — like Starbucks often does — for being too much this way, not enough that way.

      3. Use Your Email Marketing List

      Of course, it’s easy to get caught up in making sure your website is perfectly festive. However, it’s vital to remember that many customers won’t see it — unless you email them with a link and a good reason to return to your homepage.

      Long-time readers and first-time commenters alike will probably remember that we’ve gone in-depth before on why website owners need to get serious about email marketing.

      It’s the single-most-effective marketing tactic for awareness, acquisition, conversion, and retention. You want a slice of that pie!

      WordPress users! Learn how to build your own email subscriber list directly on the platform.

      Most of all remember that your subscribers opted into your email list for a reason: they want to hear from you! Don’t forget to wish them well this holiday season and share your good news.

      After all, who doesn’t love a killer sale like this offer from Legacybox?

      4. Make ‘Em Laugh

      Sometimes the best way to get your website visitors in the holiday spirit is to make them laugh.

      Of course, how you do this is largely up to you and what works for your brand.

      JibJab allows visitors to personalize hilarious videos and send them to friends and family. Each year, the site offers a series of customizable holiday cards that are bound to make their customers laugh, share, and repeat.

      Kmart is another brand that has used humor to increase sales during the holidays.

      While the Jingle Joes might not “resonate” with everyone, the use of humor is a good way to stand out during a very competitive shopping season.

      Lastly, don’t be afraid to go dark. Like real dark.

      For a lot of people, getting together with family for the holidays isn’t a friggin’ Hallmark movie. HotelTonight took all those bad feels and translated them into this dark-comedy dream.

      You don’t have to be a hotel booking website to pull this off either. Get creative and think about your specific target audience. The world is your air mattress — erm — oyster.

      5. Put Together a Holiday Gift Package

      No matter what products or services you offer, you can group them together during the holiday season and offer a holiday combo on your website.

      Dollar Shave Club nails it each year. 

      As you can see, the shave kit is exactly like the ones they offer every other month of the year.

      So what’s changed?

      Only the context! The Elf on the Shelf signals holiday hijinks are afoot without the brand having to do any repackaging of their product.

      This time of year, people like to see holiday promotions. Even if you are selling the same old thing, dress up the way you promote to match the season.

      6. Drum Up Interest

      Almost everyone has a hard time waiting for the holidays (even if you can’t wait for them to be over, amirite, Scrooge?). But as a website owner, you can use all that anticipation to drive hype for your business.

      Take H&M. The brand created a short trailer to tease its 2017 holiday collaboration with Nicki Minaj.

      I don’t know about you, but I’m a huge fan of all things H&M and Nicki Minaj, so even before the final campaign dropped, I knew I’d be checking out H&M’s latest gear. #MarketingSuccess

      Of course, if you don’t have the budget to hire a mega-watt celebrity to headline your holiday campaigns (pssst, have you heard of micro-influencers?), then you can always build hype the old-fashioned way: with a countdown!

      Ellen famously does the “12 Days of Giveaways,” and it’s hugely successful. Hitch your sleigh to that idea by doing 12 days of promotions, deals, even blog content — anything that will resonate with your customers.

      There is nothing naughty about leaning into the sense of urgency and excitement that comes with the holidays.

      7. Promote Your Expertise

      If there’s one thing for certain about the holiday season, it’s this: people gain weight. Yeah, your pants aren’t lying; holiday weight gain is real. And so is the motivation to lose the weight come January 1.

      Don’t worry I’m going somewhere with this.

      If you are a brand that holds a special level of expertise on a holiday-related topic, then the time is now to jump in and start sharing.

      For example, if you are a doctor, wellness coach, purveyor of health supplements, or self-styled weight-loss guru, then focus your content on how people can stay healthy during the holidays.

      Need an example? It’s like that one time we talked about tech-themed horror movies for Halloween. Look for a niche that you have expertise in and find a way to tie it to the season.

      Content win!

      8. Get Real With Your Followers

      Not like Drunk Uncle real. I mean genuine. The holidays are a great time to share what your brand is really about.

      Take Samsung for example.

      Their “Unwrap the Feels” video captures the spirit of the holidays by showing a collection of darling families gathering together. It’s so darn charming, that by the end, you might get a bit misty-eyed — and want to purchase some of Samsung’s magical family-bringing-together products.

      You don’t have to pull heartstrings to win hearts, though.

      If you are getting jolly around the office, let your customers in on the fun. Chances are they’ll be interested in the team that keeps their favorite products on the market.

      When you hold an office party or volunteer for a charity project, make sure you share the real, unfiltered you with your customers.

      9. Give Back to Customers

      When it comes right down to it, the holidays are about giving back. There is no better time to focus a little less on the bottom line and a little more on making the world a better place. For instance, you could make a donation to a charitable organization or sponsor a company-wide day of service.

      DYK? DreamHost is currently matching up to $10,000 for donations to Charity:Water.

      Looking for a viral way to spread joy to your customers? Host a giveaway or contest on social media.

      Last year DreamHost gave back to our customers with “The Dreamiest Website of the Year Awards.” Customers were able to submit their websites for a bevy of awards. The winners got swag, cash, and bragging rights. It was a fun way to thank the people who keep us in business.

      10. Welcome Visitors to the New Year

      After the hype has died down, take some time to ramp up your content production. Why? Because once the merriment is over, your customers will be thinking about the next big thing: the new year!

      Come January, DreamHost customers are looking for help building a brand new website to kickstart their resolutions, whether they’re starting a blog or a business. Think about what your customers will want to do next year and start creating content to help them do just that.

      The new year is a fresh start for everyone. Stay on top of your content strategy by preparing in December for a big rollout of fresh ideas in January.

      Give your website a home for the holidays. Sign up for DreamHost today!

      Stick a Bow on It, You’re Done

      There you go! We hope you’ll enjoy (and use!) these 10 gift-wrapped holiday ideas to connect with your customers during the holiday season.

      And we want you to get in on this too!

      Tell us: how have you decked out your website in years gone by? And what are you trying for the first time this December? Spread the good cheer with us on Facebook or Twitter.





      Source link