Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dockerize #28

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions client/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# Use a Node.js base image for building
FROM --platform=linux/amd64 node:20.14 AS builder

# Set the working directory
WORKDIR /app

# Copy package.json and package-lock.json
COPY ./package.json ./package-lock.json ./

# Install dependencies
RUN npm install

# Copy source code
COPY . .

# Pass build-time environment variables (only available during build stage)
ARG REACT_APP_API_URL
ENV REACT_APP_API_URL=$REACT_APP_API_URL

# Build the frontend app
RUN npm run build

# Use Nginx to serve the frontend build
FROM --platform=linux/amd64 nginx:1.23.2-alpine
COPY --from=builder /app/build /var/www/app
COPY ./infra/nginx/conf/ /etc/nginx/conf.d
EXPOSE 80 443
18 changes: 18 additions & 0 deletions client/infra/nginx/conf/default.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
server {
listen 80;
server_tokens off;

root /var/www/app;

location / {
try_files $uri /index.html;
}

location /api/ {
rewrite ^/api/(.*)$ /$1 break;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Real-Port $remote_port;
proxy_set_header Host $host;
proxy_pass http://backend:5000;
}
}
5 changes: 3 additions & 2 deletions client/src/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ import Header from './components/Header';
import WitnessStatement from './pages/TrafficTicket/WitnessStatement';
import { handleError } from './api/apiHelper';

axios.defaults.withCredentials = true;

function App() {
let mountedRef = useRef(true);
const [textContent, setTextContent] = useState('');
Expand All @@ -42,8 +44,7 @@ function App() {
// populate the app.
async function getTextContent() {
try {
let response = await axios.get('/assets/text.json');

const response = await axios.get(`${process.env.REACT_APP_API_URL}/assets/text.json`);
// Only set states if the component is mounted, otherwise return null.
if (!mountedRef.current) return null;

Expand Down
4 changes: 2 additions & 2 deletions client/src/components/BehindTheScenes.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ import parse from 'html-react-parser';

function BehindTheScenes({ title, description }) {
const parsedDescription = parse(description);
const upCaretUrl = '/assets/img/up_caret.svg';
const downCaretUrl = '/assets/img/down_caret.svg';
const upCaretUrl = `${process.env.REACT_APP_API_URL}/assets/img/up_caret.svg`;
const downCaretUrl = `${process.env.REACT_APP_API_URL}/assets/img/down_caret.svg`;
const [showDesc, setShowDesc] = useState(false);

return (
Expand Down
2 changes: 1 addition & 1 deletion client/src/components/Header.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { Link, useLocation } from 'react-router-dom';

function Header({ text }) {
const appName = 'MyGovernment';
const logoUrl = '/assets/img/logo.svg';
const logoUrl = `${process.env.REACT_APP_API_URL}/assets/img/logo.svg`;
let location = useLocation();

return (
Expand Down
2 changes: 1 addition & 1 deletion client/src/components/RequireAuth.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ function RequireAuth() {

async function isLoggedIn() {
try {
let response = await axios.get('/auth/isLoggedIn');
let response = await axios.get(`${process.env.REACT_APP_API_URL}/auth/isLoggedIn`);

// Only set states if the component is mounted, otherwise return null.
if (!mountedRef.current) return null;
Expand Down
2 changes: 1 addition & 1 deletion client/src/pages/ErrorPage.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ function ErrorPage() {
)}
<button
className="grey-button-fixed-size"
onClick={() => navigate('/index')}
onClick={() => navigate('/')}
>
{backLinkName}
</button>
Expand Down
8 changes: 4 additions & 4 deletions client/src/pages/Home.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ function Home({ text, footerText }) {
// stored for making Docusign API calls.
async function getUserInfo() {
try {
let response = await axios.get('/auth/login');
let response = await axios.get(`${process.env.REACT_APP_API_URL}/auth/login`);

// If the user revoked consent after logging in, check to make
// sure they still have consent
Expand All @@ -41,23 +41,23 @@ function Home({ text, footerText }) {
<div className="card-holder">
<Card
cardType="small-business-card"
iconUrl="/assets/img/small_business.png"
iconUrl={`${process.env.REACT_APP_API_URL}/assets/img/small_business.png`}
linkTo="/apply-for-small-business-loan"
title={text.smallBusiness}
featureList={text.smallBusinessFeatures}
buttonType="small-business-btn"
/>
<Card
cardType="traffic-ticket-card"
iconUrl="/assets/img/traffic_ticket.png"
iconUrl={`${process.env.REACT_APP_API_URL}/assets/img/traffic_ticket.png`}
linkTo="/receive-traffic-ticket"
title={text.trafficTicket}
featureList={text.trafficTicketFeatures}
buttonType="traffic-ticket-btn"
/>
<Card
cardType="passport-card"
iconUrl="/assets/img/passport.png"
iconUrl={`${process.env.REACT_APP_API_URL}/assets/img/passport.png`}
linkTo="/apply-for-passport"
title={text.passportApplication}
featureList={text.passportFeatures}
Expand Down
5 changes: 2 additions & 3 deletions client/src/pages/Login.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,15 @@ import Popup from '../components/Popup';
function Login({ text, githubText, btsText }) {
const [submitted, setSubmitted] = useState(false);
const [isOpen, setIsOpen] = useState(false);
const heroUrl = '/assets/img/hero.png';
const heroUrl = `${process.env.REACT_APP_API_URL}/assets/img/hero.png`;
let navigate = useNavigate();

// Logs the user in, and redirects the user to a consent window if
// they haven't provided consent yet.
async function handleLogin() {
try {
setSubmitted(true);

let response = await axios.get('/auth/login');
let response = await axios.get(`${process.env.REACT_APP_API_URL}/auth/login`);

// If user has never logged in before, redirect to consent screen
if (response.status === 210) {
Expand Down
4 changes: 2 additions & 2 deletions client/src/pages/Passport.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import BehindTheScenes from '../components/BehindTheScenes';
function Passport({ text, formText, btsText }) {
let navigate = useNavigate();
const [requesting, setRequesting] = useState(false);
const avatarUrl = '/assets/img/default_avatar.png';
const avatarUrl = `${process.env.REACT_APP_API_URL}/assets/img/default_avatar.png`;

// Sends POST request to server to send envelope based on the
// info the user provided in the form.
Expand All @@ -22,7 +22,7 @@ function Passport({ text, formText, btsText }) {

// Send request to server
try {
const response = await sendRequest('/passportApplication', body);
const response = await sendRequest(`${process.env.REACT_APP_API_URL}/passportApplication`, body);
console.log(response.data);

// Redirect to success screen
Expand Down
4 changes: 2 additions & 2 deletions client/src/pages/SmallBusinessLoan/SmallBusinessLoan.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import BehindTheScenes from '../../components/BehindTheScenes';
function SmallBusinessLoan({ text, formText, btsText, userFlowText }) {
let navigate = useNavigate();
const [requesting, setRequesting] = useState(false);
const avatarUrl = '/assets/img/default_avatar.png';
const avatarUrl = `${process.env.REACT_APP_API_URL}/assets/img/default_avatar.png`;

// Sends POST request to server requesting redirect URL for embedded signing
// based on the info the user put in the form.
Expand All @@ -22,7 +22,7 @@ function SmallBusinessLoan({ text, formText, btsText, userFlowText }) {

// Send request to server
try {
const response = await sendRequest('/loanApplication', body);
const response = await sendRequest(`${process.env.REACT_APP_API_URL}/loanApplication`, body);

// Received URL for embedded signing, redirect user
if (response.status === 200) {
Expand Down
6 changes: 3 additions & 3 deletions client/src/pages/SmallBusinessLoan/SubmittedLoan.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ import Success from '../Success';

function SubmittedLoan({ text }) {
let mountedRef = useRef(true);
const sageAvatarUrl = '/assets/img/sage_avatar.png';
const blaireAvatarUrl = '/assets/img/blaire_avatar.png';
const sageAvatarUrl = `${process.env.REACT_APP_API_URL}/assets/img/sage_avatar.png`;
const blaireAvatarUrl = `${process.env.REACT_APP_API_URL}/assets/img/blaire_avatar.png`;
const [lenderName, setLenderName] = useState('');
const [avatarUrl, setAvatarUrl] = useState('');
let navigate = useNavigate();
Expand All @@ -25,7 +25,7 @@ function SubmittedLoan({ text }) {
// and sets the lender name accordingly.
async function getLoanAmount() {
try {
let response = await axios.get('/loanApplication/submitted');
let response = await axios.get(`${process.env.REACT_APP_API_URL}/loanApplication/submitted`);

// Only set states if the component is mounted, otherwise return null.
if (!mountedRef.current) return null;
Expand Down
6 changes: 3 additions & 3 deletions client/src/pages/TrafficTicket/SubmittedTrafficTicket.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ import { useNavigate } from 'react-router-dom';
function SubmittedTrafficTicket({ text }) {
let navigate = useNavigate();
let mountedRef = useRef(true);
const millieAvatarUrl = '/assets/img/millie_avatar.png';
const codyAvatarUrl = '/assets/img/cody_avatar.png';
const millieAvatarUrl = `${process.env.REACT_APP_API_URL}/assets/img/millie_avatar.png`;
const codyAvatarUrl = `${process.env.REACT_APP_API_URL}/assets/img/cody_avatar.png`;
const witnessStatementUrl =
'/receive-traffic-ticket/request-witness-statement';
const mitigationClerkName = text.names.mitigationClerkName;
Expand All @@ -33,7 +33,7 @@ function SubmittedTrafficTicket({ text }) {
// description of the page accordingly.
async function getUserChoice() {
try {
let response = await axios.get('/trafficTicket/submitted');
let response = await axios.get(`${process.env.REACT_APP_API_URL}/trafficTicket/submitted`);

// Only set states if the component is mounted, otherwise return null.
if (!mountedRef.current) return null;
Expand Down
4 changes: 2 additions & 2 deletions client/src/pages/TrafficTicket/TrafficTicket.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import BehindTheScenes from '../../components/BehindTheScenes';
function TrafficTicket({ text, formText, btsText, userFlowText }) {
let navigate = useNavigate();
const [requesting, setRequesting] = useState(false);
const avatarUrl = '/assets/img/default_avatar.png';
const avatarUrl = `${process.env.REACT_APP_API_URL}/assets/img/default_avatar.png`;

// Sends POST request to server requesting redirect URL for embedded signing
// based on the info the user put in the form.
Expand All @@ -22,7 +22,7 @@ function TrafficTicket({ text, formText, btsText, userFlowText }) {

// Send request to server
try {
const response = await sendRequest('/trafficTicket', body);
const response = await sendRequest(`${process.env.REACT_APP_API_URL}/trafficTicket`, body);

// Received URL for embedded signing, redirect user
if (response.status === 200) {
Expand Down
6 changes: 3 additions & 3 deletions client/src/pages/TrafficTicket/WitnessStatement.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ function WitnessStatement({ text, formText, btsText }) {
let navigate = useNavigate();
const [requesting, setRequesting] = useState(false);
const [submitted, setSubmitted] = useState(false);
const codyAvatarUrl = '/assets/img/cody_avatar.png';
const paulaAvatarUrl = '/assets/img/paula_avatar.png';
const codyAvatarUrl = `${process.env.REACT_APP_API_URL}/assets/img/cody_avatar.png`;
const paulaAvatarUrl = `${process.env.REACT_APP_API_URL}/assets/img/paula_avatar.png`;
const policeName = text.names.policeName;
const description = text.submitted.contestedSent.description.replaceAll(
'{policeName}',
Expand All @@ -32,7 +32,7 @@ function WitnessStatement({ text, formText, btsText }) {

// Send request to server
try {
const response = await sendRequest('/trafficTicket/sms', body);
const response = await sendRequest(`${process.env.REACT_APP_API_URL}/trafficTicket/sms`, body);
console.log(response.data);

// Set submitted to true to rerender page.
Expand Down
23 changes: 23 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
version: "3.9"

services:
frontend:
build:
context: ./client
dockerfile: Dockerfile
args:
REACT_APP_API_URL: "http://localhost/api"
container_name: frontend
ports:
- 80:80
- 443:443
env_file:
- ./client/.env

backend:
build:
context: ./server
dockerfile: Dockerfile
container_name: backend
env_file:
- ./server/.env
20 changes: 20 additions & 0 deletions server/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# Use a Node.js base image
FROM --platform=linux/amd64 node:20.14

# Set the working directory
WORKDIR /app

# Copy package.json and package-lock.json
COPY ./package.json ./package-lock.json ./

# Install dependencies
RUN npm install

# Copy the rest of the backend code
COPY . .

# Expose the backend port
EXPOSE 5000

# Run the backend
CMD ["npm", "start"]
Loading