Code Monkey home page Code Monkey logo

citrustrading.ch's Introduction

Full-Stack Web Development with Django, Next.js, and Docker

This Guide provides a comprehensive set of instructions for setting up, developing, and deploying a web application using a combination of technologies including Docker, Django, and Next.js. This guide is tailored for deployment on a DigitalOcean Droplet, ensuring a smooth transition from local development to a live production environment. It covers initial setup, development configurations.


image

Index


image

Initial Setup

Prerequisites

Steps

  1. Clone the Repository

    git clone https://github.com/tarikkavaz/citrustrading.ch.git
    cd citrustrading.ch
  2. Setup Frontend Environment Variables

    cp frontend/.env-sample-local frontend/.env
  3. Install Frontend Dependencies and Build

    (cd frontend && yarn)
    (cd frontend && yarn build)
  4. Build and Run Docker Containers

    docker-compose up --build -d
  5. Initialize Django Database

    docker-compose exec backend python manage.py migrate
  6. Load Sample Data (Optional)

    docker-compose exec backend python manage.py loaddata datadump.json
  7. Create Django Superuser

    docker-compose exec backend python manage.py createsuperuser
  8. Stop the Docker

    docker-compose down

image

Development Setup

Steps

  1. Build and Run Docker Containers

    docker-compose up --build
  2. Access the Application


image

Production Setup on any Ubuntu Server

Ensure you have a clean installation of Ubuntu Server without Nginx, Docker Compose, or other related software pre-installed.

Steps

Connect to the server via SSH and run the following commands:

  1. Install Docker Engine

    sudo apt update
    sudo apt install apt-transport-https ca-certificates curl software-properties-common
    curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
    sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"
    sudo apt update
    sudo apt install docker-ce
  2. Manage Docker as a Non-root User

    sudo groupadd docker
    sudo usermod -aG docker $USER
    newgrp docker 
  3. Install Docker Compose

    sudo apt install docker-compose
  4. Install nvm and Set Node Version to 18.12.0

    curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.38.0/install.sh | bash
    echo 'export NVM_DIR="$HOME/.nvm"' >> ~/.zshrc
    echo '[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"' >> ~/.zshrc
    echo '[ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion"' >> ~/.zshrc
    source ~/.zshrc
    nvm install 18.12.0
  5. Install Yarn

    curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add -
    echo "deb https://dl.yarnpkg.com/debian/ stable main" | sudo tee /etc/apt/sources.list.d/yarn.list
    sudo apt update
    sudo apt install yarn
  6. Install Git

    sudo apt install git
  7. Configure Firewalll (Optional) Configure the firewall to allow traffic on necessary ports (80, 443, 8000, 3000):

    sudo ufw allow 80
    sudo ufw allow 443
    sudo ufw allow 8000
    sudo ufw allow 3000
  8. SSL Certificates Setup (Optional)

    If using HTTPS, set up your SSL certificates and reference them in your Nginx configuration.

  9. Running the Application Navigate to your project directory and start your Docker containers:

    docker-compose -f docker-compose.prod.yml up

Notes

  • Adjust commands as necessary for your specific Ubuntu version and server configuration.
  • Always refer to the official Docker documentation for the most up-to-date installation procedures.

image

Production Setup on Digitalocean Droplet

Prerequisites

  • Docker Droplet installed from Digitalocean Marketplace (Ubuntu 20.04)
    • Select a minimum Plan of 2 GB / 1 CPU 50 GB SSD Disk 2 TB transfer
  • Domain name pointing to the server

Steps

Connect to the server via SSH and run the following commands:

  1. Install Docker Compose

    apt install docker-compose
  2. Install nvm and set Node version to 18.12.0

    curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.38.0/install.sh | bash &&
    echo 'export NVM_DIR="$HOME/.nvm"' >> ~/.zshrc &&
    echo '[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"' >> ~/.zshrc &&
    echo '[ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion"' >> ~/.zshrc &&
    source ~/.zshrc &&
    nvm install 18.12.0
  3. Install Yarn

    curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add - &&
    echo "deb https://dl.yarnpkg.com/debian/ stable main" | sudo tee /etc/apt/sources.list.d/yarn.list &&
    sudo apt update &&
    sudo apt install yarn
  4. Clone the Repository

    git clone https://github.com/tarikkavaz/citrustrading.ch.git citrustrading.ch
    cd citrustrading.ch
  5. Setup Frontend Environment Variables

    cp frontend/.env-sample-server frontend/.env

    Ensure that the values are correctly set.

  6. Setup Nginx file

    cp nginx.conf-sample nginx.conf

    Ensure that the values YOURDOMAINNAME are correctly set.

  7. Run the Docker

    docker-compose -f docker-compose.prod.yml up --build -d &&
    docker-compose exec backend python manage.py migrate &&
    docker-compose exec backend python manage.py loaddata datadump.json &&
    docker-compose exec backend python manage.py collectstatic &&
    docker-compose exec backend python manage.py createsuperuser

    ( u:admin p:boilerplate123 )

Media File backup and restore

On local

docker run --rm -v citrustradingch_media:/data -v $(pwd):/backup ubuntu bash -c 'cd /data && tar cvf /backup/images.tar *' &&
scp images.tar citrustrading:/var/lib/docker/volumes/citrustradingch_media/_data/images

On Server

tar -xvf images.tar -C /var/lib/docker/volumes/citrustradingch_media/_data/images

image

Deploy Script Commands

Setup for Deploy Script

Before using the deploy script, set up your frontend/.env file and SSH configurations:

Edit .env File: Make sure your frontend/.env file has these lines:

SERVER_PATH=/root/yourdomainname.com
SSH_ALIAS=yoursshalias
IMAGEVOLUMEPREFIX=yourprojectname

Replace yourdomainname.com, yoursshalias, and yourprojectname with your actual server path, SSH alias, and project name.

Find Your Image Volume Name: If unsure about IMAGEVOLUMEPREFIX, run docker volume ls in the terminal. Use the name before _images from the volume list.

Ensure that your script is executable by running the following command:

chmod +x deploy.sh

Application Deployment and Maintenance Commands

To Restart Docker on server, use the following command:

./deploy.sh restart

To Pull Changes perform a git pull on the server, use the following command:

./deploy.sh pull

To update the frontend of your application, use the following command:

./deploy.sh frontend

To update the backend, use this command:

./deploy.sh backend

If you need to update both frontend and backend, use:

./deploy.sh all

To prune unused Docker objects, you can use:

./deploy.sh prune

Data Management

For data management tasks, the script supports the following commands:

To dump data:

./deploy.sh dumpdata

To load data (e.g., from a dump):

./deploy.sh loaddata

Image Volume Management

To manage images stored in a Docker volume, use the following commands.

To create a tar file of all files from the images volume on the remote server:

./deploy.sh create-tar

To download the tar file to the local root of the project:

./deploy.sh download-tar 

To extract files from the tar file to the local images volume:

./deploy.sh extract-tar

image

Bonus - Install OhMyZsh

Install zsh

sudo apt install zsh -y

Set zsh as default

chsh -s $(which zsh)

Install Oh my Zsh

sh -c "$(curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)"

Install p10k

git clone --depth=1 https://github.com/romkatv/powerlevel10k.git ~/powerlevel10k
echo 'source ~/powerlevel10k/powerlevel10k.zsh-theme' >>~/.zshrc

Source zshrc

source .zshrc

If not autoloaded, setup p10k

p10k configure

hushlogin

touch ~/.hushlogin

citrustrading.ch's People

Watchers

 avatar  avatar  avatar

citrustrading.ch's Issues

Diger dilleri ekle

De En Fr Tr

backend/config/settings.py

frontend/messages
frontend/src/middleware.tsx
frontend/src/utils/date.ts
frontend/src/app/[locale]/layout.tsx
frontend/src/components/LocaleSwitcher.tsx

"use client";

import * as React from "react";
import { useState, useEffect } from "react";
import { fetchData, SERVER_IP } from "@/utils/api";
import { Globe } from "lucide-react";
import { useLocale, useTranslations } from "next-intl";
import { Button } from "@/components/ui/button";
import { LangUrlMap } from "@/utils/types";
import { usePathname, useRouter } from "next-intl/client";
import {
  DropdownMenu,
  DropdownMenuContent,
  DropdownMenuItem,
  DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu";

async function fetchNavigationData(locale: string) {
  try {
    const endpoint = `/api/menuitems/`;
    const response = await fetchData(SERVER_IP, endpoint);
    const filteredData = response.filter((item: any) => item.lang === locale);
    return { navigations: filteredData };
  } catch (error) {
    console.error("Error fetching data:", error);
    return null;
  }
}

type PageType = "page" | "post" | "product" | "category" | "";

const langUrlMap: LangUrlMap = {
  en: {
    page: '/page/',
    post: '/post/',
    product: '/product/',
    category: '/category/',
  },
  de: {
    page: '/seite/',
    post: '/beitrag/',
    product: '/produkt/',
    category: '/kategorie/',
  },
  fr: {
    page: '/page-fr/',
    post: '/post-fr/',
    product: '/produit-fr/',
    category: '/categorie-fr/',
  },
  tr: {
    page: '/sayfa/',
    post: '/yazi/',
    product: '/urun/',
    category: '/kategori/',
  },
};

export default function LocaleSwitcher() {
  const t = useTranslations("Globals");
  const [isPending, setIsPending] = useState(false);
  const locale = useLocale();
  const router = useRouter();
  const pathname = usePathname();
  const [langSlug, setLangSlug] = useState("");
  const [slug, setSlug] = useState("");
  let [type, setType] = useState<PageType>("");

  useEffect(() => {
    const pathParts = pathname.split("/");
    const slug = pathParts.filter((part) => part !== "").pop() || "";
    setSlug(slug);

    async function fetchDataFromApi() {
      if (pathname.includes("/page/") || pathname.includes("/seite/") || pathname.includes("/page-fr/") || pathname.includes("/sayfa/")) {
        setType("page");
      } else if (pathname.includes("/post/") || pathname.includes("/beitrag/") || pathname.includes("/post-fr/") || pathname.includes("/yazi/")) {
        setType("post");
      } else if (pathname.includes("/product/") || pathname.includes("/produkt/") || pathname.includes("/produit-fr/") || pathname.includes("/urun/")) {
        setType("product");
      } else if (pathname.includes("/category/") || pathname.includes("/kategorie/") || pathname.includes("/categorie-fr/") || pathname.includes("/kategori/")) {
        setType("category");
      } else {
        setType("");
      }

      if (type) {
        const endpoint = `/api/${locale}/${type}/${slug}`;
        try {
          const data = await fetchData(SERVER_IP, endpoint);
          const langSlug = data.langslug;
          setLangSlug(langSlug);
        } catch (error) {
          console.error("Error!:", error);
        }
      }
    }

    fetchDataFromApi();
  }, [pathname, locale, type]);

  const handleLocaleChange = async (nextLocale: string) => {
    setIsPending(true);
    if (slug && langSlug && locale !== nextLocale && type) {
      const nextLangUrl = langUrlMap[nextLocale][type];
      if (nextLangUrl) {
        router.replace(`${nextLangUrl}${langSlug}`, { locale: nextLocale });
      } else {
        router.replace("/", { locale: nextLocale });
      }
    } else {
      router.replace("/", { locale: nextLocale });
    }
    setIsPending(false);
    fetchNavigationData(nextLocale).then((data) => {
      if (data) {
        fetchNavigationData(data.navigations);
      }
    });
  };
  

  return (
    <>
      <DropdownMenu>
        <DropdownMenuTrigger asChild>
          <Button variant="outline" size="icon">
            <Globe className="h-[1.2rem] w-[1.2rem] rotate-0 scale-100 transition-all " />
            <span className="sr-only">Toggle Language</span>
          </Button>
        </DropdownMenuTrigger>
        <DropdownMenuContent align="end">
          {["en", "de", "fr", "tr"].map((cur) => (
            <span key={cur}>
              <DropdownMenuItem
                onClick={() => {
                  if (locale !== cur) {
                    handleLocaleChange(cur);
                  }
                }}
                className="block text-sm p-3 space-y-1 leading-none no-underline transition-colors rounded-md outline-none cursor-pointer select-none text-foreground  hover:text-foreground hover:bg-background"
              >
                {t("localeLocale", { locale: cur })}
              </DropdownMenuItem>
            </span>
          ))}
        </DropdownMenuContent>
      </DropdownMenu>
    </>
  );
}

Font

Google font sec

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.