One place for hosting & domains

      Development

      How To Install Django and Set Up a Development Environment on Ubuntu 20.04


      Introduction

      Django is a free and open-source web framework written in Python with its core principles being scalability, re-usability and rapid development. It is also known for its framework-level consistency and loose coupling, allowing for individual components to be independent of one another.

      In this tutorial, we will set up a Django environment for development purposes on an Ubuntu 20.04 server. For a live website, you will have additional considerations, including connecting to a database, setting up a domain name, and adding layers of security. We have a variety of tutorials on Django that can help support you as you build under our Django tag.

      Prerequisites

      In order to complete this tutorial, you will need:

      Step 1 — Installing Django

      There are several ways to install Django, the Python package manager pip within a virtual environment.

      While in the server’s home directory, we’ll create the directory that will contain our Django application. Run the following command to create a directory called django-apps, or another name of your choice. Then navigate to the directory.

      • mkdir django-apps
      • cd django-apps

      While inside the django-apps directory, create your virtual environment. We’ll call it the generic env, but you should use a name that is meaningful for you and your project.

      Now, activate the virtual environment with the following command:

      You’ll know it’s activated once the prefix is changed to (env), which will look similar to the following, depending on what directory you are in:

      Within the environment, install the Django package using pip. Installing Django allows us to create and run Django applications.

      Once installed, verify your Django installation by running a version check:

      This, or something similar, will be the resulting output:

      Output

      3.0.6

      With Django installed on your server, we can move on to creating a test project to make sure everything is working correctly. We’ll be creating a skeleton web application.

      Step 2 — Adjusting Firewall Settings

      If you followed our initial server setup tutorial or have a firewall running on your server, we’ll need to open the port we’ll be using in our server’s firewall. For the UFW firewall, you can open the port with the following command:

      If you’re using DigitalOcean Firewalls, you can select HTTP from the inbound rules. You can read more about DigitalOcean Firewalls and creating rules for them by modifying the inbound rules.

      Step 3 — Starting the Project

      We now can generate an application using django-admin, a command line utility for administration tasks in Python. Then we can use the startproject command to create the project directory structure for our test website.

      While in the django-apps directory, run the following command:

      • django-admin startproject testsite

      Note: Running the django-admin startproject <projectname> command will name both project directory and project package the <projectname> and create the project in the directory in which the command was run. If the optional <destination> parameter is provided, Django will use the provided destination directory as the project directory, and create manage.py and the project package within it.

      Now we can look to see what project files were just created. Navigate to the testsite directory then list the contents of that directory to see what files were created:

      Output

      manage.py testsite

      You will notice output that shows this directory contains a file named manage.py and a folder named testsite. The manage.py file is similar to django-admin and puts the project’s package on sys.path. This also sets the DJANGO_SETTINGS_MODULE environment variable to point to your project’s settings.py file.

      You can view the manage.py script in your terminal by running the less command like so:

      When you’re finished reading the script, press q, to quit viewing the file.

      Now navigate to the testsite directory to view the other files that were created:

      Then run the following command to list the contents of the directory:

      You will see four files:

      Output

      __init__.py asgi.py settings.py urls.py wsgi.py

      Let’s go over what each of these files are:

      • __init__.py acts as the entry point for your Python project.
      • asgi.py contains the configuration for the optional deployment to the Asynchronous Server Gateway Interface or ASGI, which provides a standard for apps that are either synchronous and asynchronous, and is considered to be a successor of WSGI (see below).
      • settings.py describes the configuration of your Django installation and lets Django know which settings are available.
      • urls.py contains a urlpatterns list, that routes and maps URLs to their views.
      • wsgi.py contains the configuration for the Web Server Gateway Interface or WSGI, which provides a standard for synchronous Python apps.

      Note: Although default files are generated, you still have the ability to tweak the asgi.py or wsgi.py files at any time to fit your deployment needs.

      Step 4 — Configuring Django

      Now we can start the server and view the website on a designated host and port by running the runserver command.

      We’ll need to add your server ip address to the list of ALLOWED_HOSTS in the settings.py file located in ~/test_django_app/testsite/testsite/.

      As stated in the Django docs, the ALLOWED_HOSTS variable contains “a list of strings representing the host/domain names that this Django site can serve. This is a security measure to prevent HTTP Host header attacks, which are possible even under many seemingly-safe web server configurations.”

      You can use your favorite text editor to add your IP address. For example, if you’re using nano, run the following command:

      • nano ~/django-apps/testsite/testsite/settings.py

      Once you run the command, you’ll want to navigate to the Allowed Hosts Section of the document and add your server’s IP address inside the square brackets within single or double quotes.

      settings.py

      """
      Django settings for testsite project.
      
      Generated by 'django-admin startproject' using Django 2.0.
      ...
      """
      ...
      # SECURITY WARNING: don't run with debug turned on in production!
      DEBUG = True
      
      # Edit the line below with your server IP address
      ALLOWED_HOSTS = ['your-server-ip']
      ...
      

      You can save the change and exit nano by holding down the CTRL + x keys and then pressing the y key. Next, we’ll go on to access our web app via a browser.

      Finally, let’s create an administrative user so that you can use the Djano admin interface. Let’s do this with the createsuperuser command:

      • python manage.py createsuperuser

      You will be prompted for a username, an email address, and a password for your user.

      Step 5 — Accessing the Django Web App

      With our configuration completed, be sure to navigate back to the directory where manage.py is located:

      • cd ~/django-apps/testsite/

      Now, run the following command replacing the your-server-ip text with the IP of your server:

      • python manage.py runserver 0.0.0.0:8000

      Finally, you can navigate to the below link to see what your skeleton website looks like, again replacing the highlighted text with your server’s actual IP:

      http://your-server-ip:8000/
      

      Once the page loads, you’ll see the following:

      Django Default Page

      This confirms that Django was properly installed and our test project is working correctly.

      To access the admin interface, add /admin/ to the end of your URL:

      http://your_server_ip:8000/admin/
      

      This will take you to a login screen:

      Django admin login

      If you enter the admin username and password that you just created, you will have access to the main admin section of the site:

      Django admin page

      For more information about working with the Django admin interface, please see “How To Enable and Connect the Django Admin Interface.”

      When you are done with testing your app, you can press CTRL + C to stop the runserver command. This will return you to your programming environment.

      When you are ready to leave your Python environment, you can run the deactivate command:

      Deactivating your programming environment will put you back to the terminal command prompt.

      Conclusion

      In this tutorial you have successfully installed Django and set up a development environment to begin working on your Django app.

      You now have the foundation needed to get started building Django web applications.



      Source link

      How To Use Visual Studio Code for Remote Development via the Remote-SSH Plugin


      Introduction

      Visual Studio Code is a popular Integrated Developer Environment (IDE) for developers. Its large selection of plugins, minimal design, and cross-platform support make it a great choice for developers of all levels. This tutorial focuses on using the Remote-SSH plugin to enable remote software development. With this plugin you can edit files on your local workstation, but run development tasks such as program execution, unit tests, or static analysis on a remote server.

      There are many reasons why this may be beneficial to you. For example, you may have a Windows workstation and want to develop on Windows, but your code will eventually run on Linux. You may need more RAM or processing power than your current machine has available, or you want to keep code off of your personal machine due to a company policy, or the desire to keep your workstation prestine.

      In this tutorial, you’ll enable the Remote-SSH plugin, configure Visual Studio Code to execute code on the remote server, and execute code from your local Visual Studio Code installation on the remote server.

      Prerequisites

      In order to follow along with this guide, you’ll need:

      • A local development machine running Windows, MacOSX, or Linux. This tutorial will not work on ChromeOS devices.
      • Visual Studio Code, which you can download and install from the official web site.
      • An SSH key pair generated:
      • One Ubuntu 18.04 server set up by following the Ubuntu 18.04 initial server setup guide, including a non-root sudo-enabled user and a firewall.

      Step 1 — Installing the Remote-SSH Plugin

      The Extensions Marketplace is where you can download supported and third-party extensions for a variety of different tools and programming languages. This is where you will search for the Remote-SSH plugin and install it.

      On the left-hand side of the IDE there is a vertical row of five icons. The bottom icon, which looks like four squares in a box with the top right square exploding out, is the icon for the Extensions Marketplace:

      Extensions Marketplace Icon Location

      You can also access this section by pressing Ctrl+Shift+X. When you open this page you will see suggested plugins to download and install.

      Once you have the Extensions Marketplace open, type Remote-SSH in the Search Extensions in Marketplace search bar. When you find the plugin, select it and then click the green Install button to install the extension.

      Search for the Remote SSH Plugin

      The extension is now installed. Next, you’ll configure the extension so you can connect to your server.

      Step 2 — Configuring the Remote-SSH Plugin and Connecting To Your Server

      Now that you have the plugin installed you can configure it to connect to a server. To do so, you’ll need the following pieces of information:

      • The server’s IP or hostname.
      • The username you’ll connect with.
      • The private key you’ll use to authenticate your user.

      You’ll use this information to create an SSH configuration file that Visual Studio Code can use to SSH to the server to sync files and execute code on your behalf. You will create this configuration using Visual Studio Code.

      Now that you have the Remote-SSH plugin installed, you’ll see a small green box in the bottom left-hand corner of the Visual Studio Code interface. If you hover over the box with your mouse pointer, the popup will say Open a remote window. The button looks like a greater than sign slightly under a less than sign ><, like the one in the following image:

      Open a remote window green UI button

      Click the button, and a dialog box appears in the top center. Select Remote-SSH: Open Configuration File… from the list:

      Selecting Configure SSH in the UI

      The next prompt will ask you which configuration file you want to open. If you’re on Windows, you’ll see two locations: one in your personal user directory, and one in the installation location for SSH. You should use the file in your user directory when configuring the server.

      Select the file and your editor will open the config file. Add the following code to the file to define the connection to your server, replacing the highlighted sections with the information for your server:

      config

      Host my_remote_server
          HostName your_server_ip_or_hostname
          User sammy
          IdentityFile /location/of/your/private/key
      

      Here’s how this configuration file works:

      • Host: This specifies a name for your host. This lets you use a short name or abbreviation instead of the full IP address or host name when connecting to the server.
      • HostName: The actual hostname of the server, which is either an IP address or a fully qualified domain name.
      • User: The user you want to use to connect with.
      • IdentityFile: The path to your SSH private key. On Mac and Linux systems, you’ll find this in your home directory in a hidden .ssh directory, typically called id_rsa. If you are on Windows you will have specified a location to save this file when you created it using putty-gen.

      Specify the appropriate values in your file and save the file.

      Visual Studio Code is now configured and ready to connect to your server. Click on the green Open a remote window button in the bottom left-hand corner and select Remote-SSH: Connect to Host…

      Connecting to the Server from Visual Studio Code

      Once you’ve done this all the availble and configured servers will appear in the dropdown menu. Select the server that you want to connect to from this list.

      If this is the first time you have connected to this server from your machine, you’ll likely be prompted with the SSH Fingerprint verification dialog, like the one in the following image:

      Confirming your SSH Fingerprint

      This is to ensure that you are really connecting to the server you think you are. You can verify this by logging in to your server manually and running ssh-keygen -l -f /etc/ssh/ssh_host_key.pub to view the fingerprint of the server. If this fingerprint is the same as the one being presented to you in Visual Studio Code, then you are indeed connecting to the server you think you are so you can click Continue.

      Visual Studio Code defaults to opening a new window when a new connection is made. A new window will appear with the welcome screen. You’ll know that your connection was successful if you see SSH: your_ip_address_or_hostname in the green box in the bottom left-hand corner. This means that Visual Studio Code is connected and communicating with your remote server.

      Successful SSH connection

      Now that you’re connected, you can run commands and code from your editor.

      Step 3 — Executing Code on the Remote Server

      The Remote-SSH plugin is configured, and it’s time to run some code on your remote machine. Open a terminal window by selecting Terminal from the navigation bar at the top of the Visual Studio window and clicking New Terminal. You can also open a terminal by pressing CTRL+Shift+`. The terminal that is opened is a terminal on your remote server, not one on your local machine.

      When the terminal opens, issue the following command to view the IP address of your server to verify that you are connected to your remote server:

      You’ll see the following output in your terminal:

      Output

      1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo valid_lft forever preferred_lft forever inet6 ::1/128 scope host valid_lft forever preferred_lft forever 2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000 link/ether 16:cb:05:5b:30:f1 brd ff:ff:ff:ff:ff:ff inet your_server_ip brd your_broadcast_address scope global eth0 valid_lft forever preferred_lft forever ...

      To test out the ability to run remote code, create a new Python file called hello.py in your editor. When you are connected to your remote server, all files created through Visual Studio Code will be saved to that server, not on your local machine.

      Add the following contents to the file:

      hello.py

      print("Hello Sammy!")
      

      To run this program on your server, open a terminal in Visual Studio Code from the navigation menu or by pressing the key sequence CTRL+Shift+`. Since this terminal session is connected to your remote server, run the following command in the terminal to execute your hello.py program:

      Your program’s output will be displayed.

      Executing your Python Script

      You can also execute the file from the Debug context menu by selecting Run without Debugging.

      Note: If you have any development extensions installed in Visual Studio Code, like the Python extension, you will have to reinstall these extensions on your server through the Extension Marketplace. If you have previously installed these plugins in Visual Studio Code, when you search for them again, the Marketplace will say Install on SSH: hostname. Always pay attention to what devlopment context you are in, because this is where Visual Studio Code will install your plugins and create your files. If you try to run your code without these plugins installed, error dialog boxes will appear in the bottom right-hand corner of the screen prompting you to install them on your remote server. After you have installed these they will likely require you to reload Visual Studio Code. When you relaunch it, it will continue working on the remote server without you having to manually reconnect.

      Conclusion

      You now have Visual Studio Code configured for development on a remote server using SSH. Remote execution with an IDE provides many benefits, including the ability to quickly test how your code runs on different operating systems and different hardware specifications. As long as you have an internet connection you could connect to your server and work on your code from any computer, and you’ll be able to develop using a Linux environment even if you run Windows as your primary operating system.



      Source link

      How to Containerize a Laravel 6 Application for Development with Docker Compose on Ubuntu 18.04


      Introduction

      To containerize an application refers to the process of adapting an application and its components in order to be able to run it in lightweight environments known as containers. Such environments are isolated and disposable, and can be leveraged for developing, testing, and deploying applications to production.

      In this guide, we’ll use Docker Compose to containerize a Laravel 6 application for development. When you’re finished, you’ll have a demo Laravel application running on three separate service containers:

      • An app service running PHP7.4-FPM;
      • A db service running MySQL 5.7;
      • An nginx service that uses the app service to parse PHP code before serving the Laravel application to the final user.

      To allow for a streamlined development process and facilitate application debugging, we’ll keep application files in sync by using shared volumes. We’ll also see how to use docker-compose exec commands to run Composer and Artisan on the app container.

      Prerequisites

      Step 1 — Obtaining the Demo Application

      To get started, we’ll fetch the demo Laravel application from its Github repository. We’re interested in the tutorial-01 branch, which contains the basic Laravel application we’ve created in the first guide of this series.

      To obtain the application code that is compatible with this tutorial, download release tutorial-1.0.1 to your home directory with:

      • cd ~
      • curl -L https://github.com/do-community/travellist-laravel-demo/archive/tutorial-1.0.1.zip -o travellist.zip

      We’ll need the unzip command to unpack the application code. In case you haven’t installed this package before, do so now with:

      • sudo apt update
      • sudo apt install unzip

      Now, unzip the contents of the application and rename the unpacked directory for easier access:

      • unzip travellist.zip
      • mv travellist-laravel-demo-tutorial-1.0.1 travellist-demo

      Navigate to the travellist-demo directory:

      In the next step, we’ll create a .env configuration file to set up the application.

      Step 2 — Setting Up the Application’s .env File

      The Laravel configuration files are located in a directory called config, inside the application’s root directory. Additionally, a .env file is used to set up environment-dependent configuration, such as credentials and any information that might vary between deploys. This file is not included in revision control.

      Warning: The environment configuration file contains sensitive information about your server, including database credentials and security keys. For that reason, you should never share this file publicly.

      The values contained in the .env file will take precedence over the values set in regular configuration files located at the config directory. Each installation on a new environment requires a tailored environment file to define things such as database connection settings, debug options, application URL, among other items that may vary depending on which environment the application is running.

      We’ll now create a new .env file to customize the configuration options for the development environment we’re setting up. Laravel comes with an example.env file that we can copy to create our own:

      Open this file using nano or your text editor of choice:

      The current .env file from the travellist demo application contains settings to use a local MySQL database, with 127.0.0.1 as database host. We need to update the DB_HOST variable so that it points to the database service we will create in our Docker environment. In this guide, we’ll call our database service db. Go ahead and replace the listed value of DB_HOST with the database service name:

      .env

      APP_NAME=Travellist
      APP_ENV=dev
      APP_KEY=
      APP_DEBUG=true
      APP_URL=http://localhost:8000
      
      LOG_CHANNEL=stack
      
      DB_CONNECTION=mysql
      DB_HOST=db
      DB_PORT=3306
      DB_DATABASE=travellist
      DB_USERNAME=travellist_user
      DB_PASSWORD=password
      ...
      

      Feel free to also change the database name, username, and password, if you wish. These variables will be leveraged in a later step where we’ll set up the docker-compose.yml file to configure our services.

      Save the file when you’re done editing. If you used nano, you can do that by pressing Ctrl+x, then Y and Enter to confirm.

      Step 3 — Setting Up the Application’s Dockerfile

      Although both our MySQL and Nginx services will be based on default images obtained from the Docker Hub, we still need to build a custom image for the application container. We’ll create a new Dockerfile for that.

      Our travellist image will be based on the php:7.4-fpm official PHP image from Docker Hub. On top of that basic PHP-FPM environment, we’ll install a few extra PHP modules and the Composer dependency management tool.

      We’ll also create a new system user; this is necessary to execute artisan and composer commands while developing the application. The uid setting ensures that the user inside the container has the same uid as your system user on your host machine, where you’re running Docker. This way, any files created by these commands are replicated in the host with the correct permissions. This also means that you’ll be able to use your code editor of choice in the host machine to develop the application that is running inside containers.

      Create a new Dockerfile with:

      Copy the following contents to your Dockerfile:

      Dockerfile

      FROM php:7.4-fpm
      
      # Arguments defined in docker-compose.yml
      ARG user
      ARG uid
      
      # Install system dependencies
      RUN apt-get update && apt-get install -y 
          git 
          curl 
          libpng-dev 
          libonig-dev 
          libxml2-dev 
          zip 
          unzip
      
      # Clear cache
      RUN apt-get clean && rm -rf /var/lib/apt/lists/*
      
      # Install PHP extensions
      RUN docker-php-ext-install pdo_mysql mbstring exif pcntl bcmath gd
      
      # Get latest Composer
      COPY --from=composer:latest /usr/bin/composer /usr/bin/composer
      
      # Create system user to run Composer and Artisan Commands
      RUN useradd -G www-data,root -u $uid -d /home/$user $user
      RUN mkdir -p /home/$user/.composer && 
          chown -R $user:$user /home/$user
      
      # Set working directory
      WORKDIR /var/www
      
      USER $user
      
      

      Don’t forget to save the file when you’re done.

      Our Dockerfile starts by defining the base image we’re using: php:7.4-fpm.

      After installing system packages and PHP extensions, we install Composer by copying the composer executable from its latest official image to our own application image.

      A new system user is then created and set up using the user and uid arguments that were declared at the beginning of the Dockerfile. These values will be injected by Docker Compose at build time.

      Finally, we set the default working dir as /var/www and change to the newly created user. This will make sure you’re connecting as a regular user, and that you’re on the right directory, when running composer and artisan commands on the application container.

      Step 4 — Setting Up Nginx Configuration and Database Dump Files

      When creating development environments with Docker Compose, it is often necessary to share configuration or initialization files with service containers, in order to set up or bootstrap those services. This practice facilitates making changes to configuration files to fine-tune your environment while you’re developing the application.

      We’ll now set up a folder with files that will be used to configure and initialize our service containers.

      To set up Nginx, we’ll share a travellist.conf file that will configure how the application is served. Create the docker-compose/nginx folder with:

      • mkdir -p docker-compose/nginx

      Open a new file named travellist.conf within that directory:

      • nano docker-compose/nginx/travellist.conf

      Copy the following Nginx configuration to that file:

      docker-compose/nginx/travellist.conf

      
      server {
          listen 80;
          index index.php index.html;
          error_log  /var/log/nginx/error.log;
          access_log /var/log/nginx/access.log;
          root /var/www/public;
          location ~ .php$ {
              try_files $uri =404;
              fastcgi_split_path_info ^(.+.php)(/.+)$;
              fastcgi_pass app:9000;
              fastcgi_index index.php;
              include fastcgi_params;
              fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
              fastcgi_param PATH_INFO $fastcgi_path_info;
          }
          location / {
              try_files $uri $uri/ /index.php?$query_string;
              gzip_static on;
          }
      }
      

      This file will configure Nginx to listen on port 80 and use index.php as default index page. It will set the document root to /var/www/public, and then configure Nginx to use the app service on port 9000 to process *.php files.

      Save and close the file when you’re done editing.

      To set up the MySQL database, we’ll share a database dump that will be imported when the container is initialized. This is a feature provided by the MySQL 5.7 image we’ll be using on that container.

      Create a new folder for your MySQL initialization files inside the docker-compose folder:

      • mkdir docker-compose/mysql

      Open a new .sql file:

      • nano docker-compose/mysql/init_db.sql

      The following MySQL dump is based on the database we’ve set up in our Laravel on LEMP guide. It will create a new table named places. Then, it will populate the table with a set of sample places.

      Add the following code to the file:

      docker-compose/mysql/db_init.sql

      DROP TABLE IF EXISTS `places`;
      
      CREATE TABLE `places` (
        `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
        `name` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
        `visited` tinyint(1) NOT NULL DEFAULT '0',
        PRIMARY KEY (`id`)
      ) ENGINE=InnoDB AUTO_INCREMENT=12 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
      
      INSERT INTO `places` (name, visited) VALUES ('Berlin',0),('Budapest',0),('Cincinnati',1),('Denver',0),('Helsinki',0),('Lisbon',0),('Moscow',1),('Nairobi',0),('Oslo',1),('Rio',0),('Tokyo',0);
      

      The places table contains three fields: id, name, and visited. The visited field is a flag used to identify the places that are still to go. Feel free to change the sample places or include new ones. Save and close the file when you’re done.

      We’ve finished setting up the application’s Dockerfile and the service configuration files. Next, we’ll set up Docker Compose to use these files when creating our services.

      Step 5 — Creating a Multi-Container Environment with Docker Compose

      Docker Compose enables you to create multi-container environments for applications running on Docker. It uses service definitions to build fully customizable environments with multiple containers that can share networks and data volumes. This allows for a seamless integration between application components.

      To set up our service definitions, we’ll create a new file called docker-compose.yml. Typically, this file is located at the root of the application folder, and it defines your containerized environment, including the base images you will use to build your containers, and how your services will interact.

      We’ll define three different services in our docker-compose.yml file: app, db, and nginx.

      The app service will build an image called travellist, based on the Dockerfile we’ve previously created. The container defined by this service will run a php-fpm server to parse PHP code and send the results back to the nginx service, which will be running on a separate container. The mysql service defines a container running a MySQL 5.7 server. Our services will share a bridge network named travellist.

      The application files will be synchronized on both the app and the nginx services via bind mounts. Bind mounts are useful in development environments because they allow for a performant two-way sync between host machine and containers.

      Create a new docker-compose.yml file at the root of the application folder:

      A typical docker-compose.yml file starts with a version definition, followed by a services node, under which all services are defined. Shared networks are usually defined at the bottom of that file.

      To get started, copy this boilerplate code into your docker-compose.yml file:

      docker-compose.yml

      version: "3.7"
      services:
      
      
      networks:
        travellist:
          driver: bridge
      

      We’ll now edit the services node to include the app, db and nginx services.

      The app Service

      The app service will set up a container named travellist-app. It builds a new Docker image based on a Dockerfile located in the same path as the docker-compose.yml file. The new image will be saved locally under the name travellist.

      Even though the document root being served as the application is located in the nginx container, we need the application files somewhere inside the app container as well, so we’re able to execute command line tasks with the Laravel Artisan tool.

      Copy the following service definition under your services node, inside the docker-compose.yml file:

      docker-compose.yml

        app:
          build:
            args:
              user: sammy
              uid: 1000
            context: ./
            dockerfile: Dockerfile
          image: travellist
          container_name: travellist-app
          restart: unless-stopped
          working_dir: /var/www/
          volumes:
            - ./:/var/www
          networks:
            - travellist
      

      These settings do the following:

      • build: This configuration tells Docker Compose to build a local image for the app service, using the specified path (context) and Dockerfile for instructions. The arguments user and uid are injected into the Dockerfile to customize user creation commands at build time.
      • image: The name that will be used for the image being built.
      • container_name: Sets up the container name for this service.
      • restart: Always restart, unless the service is stopped.
      • working_dir: Sets the default directory for this service as /var/www.
      • volumes: Creates a shared volume that will synchronize contents from the current directory to /var/www inside the container. Notice that this is not your document root, since that will live in the nginx container.
      • networks: Sets up this service to use a network named travellist.

      The db Service

      The db service uses a pre-built MySQL 5.7 image from Docker Hub. Because Docker Compose automatically loads .env variable files located in the same directory as the docker-compose.yml file, we can obtain our database settings from the Laravel .env file we created in a previous step.

      Include the following service definition in your services node, right after the app service:

      docker-compose.yml

        db:
          image: mysql:5.7
          container_name: travellist-db
          restart: unless-stopped
          environment:
            MYSQL_DATABASE: ${DB_DATABASE}
            MYSQL_ROOT_PASSWORD: ${DB_PASSWORD}
            MYSQL_PASSWORD: ${DB_PASSWORD}
            MYSQL_USER: ${DB_USERNAME}
            SERVICE_TAGS: dev
            SERVICE_NAME: mysql
          volumes:
            - ./docker-compose/mysql:/docker-entrypoint-initdb.d
          networks:
            - travellist
      

      These settings do the following:

      • image: Defines the Docker image that should be used for this container. In this case, we’re using a MySQL 5.7 image from Docker Hub.
      • container_name: Sets up the container name for this service: travellist-db.
      • restart: Always restart this service, unless it is explicitly stopped.
      • environment: Defines environment variables in the new container. We’re using values obtained from the Laravel .env file to set up our MySQL service, which will automatically create a new database and user based on the provided environment variables.
      • volumes: Creates a volume to share a .sql database dump that will be used to initialize the application database. The MySQL image will automatically import .sql files placed in the /docker-entrypoint-initdb.d directory inside the container.
      • networks: Sets up this service to use a network named travellist.

      The nginx Service

      The nginx service uses a pre-built Nginx image on top of Alpine, a lightweight Linux distribution. It creates a container named travellist-nginx, and it uses the ports definition to create a redirection from port 8000 on the host system to port 80 inside the container.

      Include the following service definition in your services node, right after the db service:

      docker-compose.yml

        nginx:
          image: nginx:1.17-alpine
          container_name: travellist-nginx
          restart: unless-stopped
          ports:
            - 8000:80
          volumes:
            - ./:/var/www
            - ./docker-compose/nginx:/etc/nginx/conf.d
          networks:
            - travellist
      

      These settings do the following:

      • image: Defines the Docker image that should be used for this container. In this case, we’re using the Alpine Nginx 1.17 image.
      • container_name: Sets up the container name for this service: travellist-nginx.
      • restart: Always restart this service, unless it is explicitly stopped.
      • ports: Sets up a port redirection that will allow external access via port 8000 to the web server running on port 80 inside the container.
      • volumes: Creates two shared volumes. The first one will synchronize contents from the current directory to /var/www inside the container. This way, when you make local changes to the application files, they will be quickly reflected in the application being served by Nginx inside the container. The second volume will make sure our Nginx configuration file, located at docker-compose/nginx/travellist.conf, is copied to the container’s Nginx configuration folder.
      • networks: Sets up this service to use a network named travellist.

      Finished docker-compose.yml File

      This is how our finished docker-compose.yml file looks like:

      docker-compose.yml

      version: "3.7"
      services:
        app:
          build:
            args:
              user: sammy
              uid: 1000
            context: ./
            dockerfile: Dockerfile
          image: travellist
          container_name: travellist-app
          restart: unless-stopped
          working_dir: /var/www/
          volumes:
            - ./:/var/www
          networks:
            - travellist
      
        db:
          image: mysql:5.7
          container_name: travellist-db
          restart: unless-stopped
          environment:
            MYSQL_DATABASE: ${DB_DATABASE}
            MYSQL_ROOT_PASSWORD: ${DB_PASSWORD}
            MYSQL_PASSWORD: ${DB_PASSWORD}
            MYSQL_USER: ${DB_USERNAME}
            SERVICE_TAGS: dev
            SERVICE_NAME: mysql
          volumes:
            - ./docker-compose/mysql:/docker-entrypoint-initdb.d
          networks:
            - travellist
      
        nginx:
          image: nginx:alpine
          container_name: travellist-nginx
          restart: unless-stopped
          ports:
            - 8000:80
          volumes:
            - ./:/var/www
            - ./docker-compose/nginx:/etc/nginx/conf.d/
          networks:
            - travellist
      
      networks:
        travellist:
          driver: bridge
      

      Make sure you save the file when you’re done.

      Step 6 — Running the Application with Docker Compose

      We’ll now use docker-compose commands to build the application image and run the services we specified in our setup.

      Build the app image with the following command:

      This command might take a few minutes to complete. You’ll see output similar to this:

      Output

      Building app Step 1/11 : FROM php:7.4-fpm ---> fa37bd6db22a Step 2/11 : ARG user ---> Running in f71eb33b7459 Removing intermediate container f71eb33b7459 ---> 533c30216f34 Step 3/11 : ARG uid ---> Running in 60d2d2a84cda Removing intermediate container 60d2d2a84cda ---> 497fbf904605 Step 4/11 : RUN apt-get update && apt-get install -y git curl libpng-dev libonig-dev ... Step 7/11 : COPY --from=composer:latest /usr/bin/composer /usr/bin/composer ---> e499f74896e3 Step 8/11 : RUN useradd -G www-data,root -u $uid -d /home/$user $user ---> Running in 232ef9c7dbd1 Removing intermediate container 232ef9c7dbd1 ---> 870fa3220ffa Step 9/11 : RUN mkdir -p /home/$user/.composer && chown -R $user:$user /home/$user ---> Running in 7ca8c0cb7f09 Removing intermediate container 7ca8c0cb7f09 ---> 3d2ef9519a8e Step 10/11 : WORKDIR /var/www ---> Running in 4a964f91edfa Removing intermediate container 4a964f91edfa ---> 00ada639da21 Step 11/11 : USER $user ---> Running in 9f8e874fede9 Removing intermediate container 9f8e874fede9 ---> fe176ff4702b Successfully built fe176ff4702b Successfully tagged travellist:latest

      When the build is finished, you can run the environment in background mode with:

      Output

      Creating travellist-db ... done Creating travellist-app ... done Creating travellist-nginx ... done

      This will run your containers in the background. To show information about the state of your active services, run:

      You’ll see output like this:

      Output

      Name Command State Ports ------------------------------------------------------------------------------- travellist-app docker-php-entrypoint php-fpm Up 9000/tcp travellist-db docker-entrypoint.sh mysqld Up 3306/tcp, 33060/tcp travellist-nginx nginx -g daemon off; Up 0.0.0.0:8000->80/tcp

      Your environment is now up and running, but we still need to execute a couple commands to finish setting up the application. You can use the docker-compose exec command to execute commands in the service containers, such as an ls -l to show detailed information about files in the application directory:

      • docker-compose exec app ls -l

      Output

      total 256 -rw-rw-r-- 1 sammy 1001 738 Jan 15 16:46 Dockerfile -rw-rw-r-- 1 sammy 1001 101 Jan 7 08:05 README.md drwxrwxr-x 6 sammy 1001 4096 Jan 7 08:05 app -rwxr-xr-x 1 sammy 1001 1686 Jan 7 08:05 artisan drwxrwxr-x 3 sammy 1001 4096 Jan 7 08:05 bootstrap -rw-rw-r-- 1 sammy 1001 1501 Jan 7 08:05 composer.json -rw-rw-r-- 1 sammy 1001 179071 Jan 7 08:05 composer.lock drwxrwxr-x 2 sammy 1001 4096 Jan 7 08:05 config drwxrwxr-x 5 sammy 1001 4096 Jan 7 08:05 database drwxrwxr-x 4 sammy 1001 4096 Jan 15 16:46 docker-compose -rw-rw-r-- 1 sammy 1001 1015 Jan 15 16:45 docker-compose.yml -rw-rw-r-- 1 sammy 1001 1013 Jan 7 08:05 package.json -rw-rw-r-- 1 sammy 1001 1405 Jan 7 08:05 phpunit.xml drwxrwxr-x 2 sammy 1001 4096 Jan 7 08:05 public -rw-rw-r-- 1 sammy 1001 273 Jan 7 08:05 readme.md drwxrwxr-x 6 sammy 1001 4096 Jan 7 08:05 resources drwxrwxr-x 2 sammy 1001 4096 Jan 7 08:05 routes -rw-rw-r-- 1 sammy 1001 563 Jan 7 08:05 server.php drwxrwxr-x 5 sammy 1001 4096 Jan 7 08:05 storage drwxrwxr-x 4 sammy 1001 4096 Jan 7 08:05 tests -rw-rw-r-- 1 sammy 1001 538 Jan 7 08:05 webpack.mix.js

      We’ll now run composer install to install the application dependencies:

      • docker-compose exec app composer install

      You’ll see output like this:

      Output

      Loading composer repositories with package information Installing dependencies (including require-dev) from lock file Package operations: 85 installs, 0 updates, 0 removals - Installing doctrine/inflector (1.3.1): Downloading (100%) - Installing doctrine/lexer (1.2.0): Downloading (100%) - Installing dragonmantank/cron-expression (v2.3.0): Downloading (100%) - Installing erusev/parsedown (1.7.4): Downloading (100%) - Installing symfony/polyfill-ctype (v1.13.1): Downloading (100%) - Installing phpoption/phpoption (1.7.2): Downloading (100%) - Installing vlucas/phpdotenv (v3.6.0): Downloading (100%) - Installing symfony/css-selector (v5.0.2): Downloading (100%) … Generating optimized autoload files > IlluminateFoundationComposerScripts::postAutoloadDump > @php artisan package:discover --ansi Discovered Package: facade/ignition Discovered Package: fideloper/proxy Discovered Package: laravel/tinker Discovered Package: nesbot/carbon Discovered Package: nunomaduro/collision Package manifest generated successfully.

      The last thing we need to do before testing the application is to generate a unique application key with the artisan Laravel command-line tool. This key is used to encrypt user sessions and other sensitive data:

      • docker-compose exec app php artisan key:generate

      Output

      Application key set successfully.

      Now go to your browser and access your server’s domain name or IP address on port 8000:

      http://server_domain_or_IP:8000
      

      You’ll see a page like this:

      Demo Laravel Application

      You can use the logs command to check the logs generated by your services:

      • docker-compose logs nginx
      Attaching to travellist-nginx
      travellist-nginx | 192.168.160.1 - - [23/Jan/2020:13:57:25 +0000] "GET / HTTP/1.1" 200 626 "-" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36"
      travellist-nginx | 192.168.160.1 - - [23/Jan/2020:13:57:26 +0000] "GET /favicon.ico HTTP/1.1" 200 0 "http://localhost:8000/" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36"
      travellist-nginx | 192.168.160.1 - - [23/Jan/2020:13:57:42 +0000] "GET / HTTP/1.1" 200 626 "-" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36"
      …
      

      If you want to pause your Docker Compose environment while keeping the state of all its services, run:

      Output

      Pausing travellist-db ... done Pausing travellist-nginx ... done Pausing travellist-app ... done

      You can then resume your services with:

      Output

      Unpausing travellist-app ... done Unpausing travellist-nginx ... done Unpausing travellist-db ... done

      To shut down your Docker Compose environment and remove all of its containers, networks, and volumes, run:

      Output

      Stopping travellist-nginx ... done Stopping travellist-db ... done Stopping travellist-app ... done Removing travellist-nginx ... done Removing travellist-db ... done Removing travellist-app ... done Removing network travellist-laravel-demo_travellist

      For an overview of all Docker Compose commands, please check the Docker Compose command-line reference.

      Conclusion

      In this guide, we’ve set up a Docker environment with three containers using Docker Compose to define our infrastructure in a YAML file.

      From this point on, you can work on your Laravel application without needing to install and set up a local web server for development and testing. Moreover, you’ll be working with a disposable environment that can be easily replicated and distributed, which can be helpful while developing your application and also when moving towards a production environment.



      Source link