Built at: 2024-10-16T09:55:25.150Z Skip to content

part3b

Deploying app to internet

CORS

frontend:

revise src/services/notes.jsx, baseUrl changed from “http://localhost:3001/notes” to “http://localhost:3001/api/notes” to match the Express backend.

notes.jsx
const baseUrl = "http://localhost:3001/api/notes";

Now frontend’s GET request to http://localhost:3001/api/notes does not work for some reason.

revise on backend:

Terminal window
pnpm i cors

revise backend index.js

index.js
const cors = require("cors");
app.use(cors());

It works now, except the change important function(which has not been done on the backend yet).

proxy

revise on frontend:

To make the baseUrl in relative path:

src/services/notes.js
const baseUrl = "/api/notes";

Change the vite.config.js, add the proxy beforehand.

vite.config.js
import { defineConfig } from "vite";
import react from "@vitejs/plugin-react";
// https://vitejs.dev/config/
export default defineConfig({
plugins: [react()],
server: {
proxy: {
"/api": {
target: "http://localhost:3001",
changeOrigin: true,
},
},
},
});

Application to the Internet

backend:

index.js
const PORT = process.env.PORT || 3001
app.listen(PORT, () => {
console.log(`Server running on port ${PORT}`)
})

Fly.io

Install flyctl

https://fly.io/docs/hands-on/install-flyctl/

https://mirrors.sdu.edu.cn/github-release/1702434474/github-release/PowerShell_PowerShell/
https://github.com/PowerShell/PowerShell/releases/download/v7.4.4/PowerShell-7.4.4-win-x64.msi
https://github.moeyy.xyz/

flyctl auth login
stuck at Waiting for session...⣷
flyctl auth signup --verbose | tee temp
Opening https://fly.io/app/auth/cli/...
Login in the opened browser
successfully logged in as ...
flyctl launch --no-deploy
Y
opened a browser, change name and region, confirm
...
Waiting for launch data... Done
Created app 'backend-fullstackopen-cn' in organization 'personal'
Admin URL: https://fly.io/apps/backend-fullstackopen-cn
Hostname: backend-fullstackopen-cn.fly.dev
installing: npx --yes @flydotio/dockerfile@latest
create Dockerfile
Wrote config file fly.toml
Validating part3\backend\fly.toml
✓ Configuration is valid

Got the Dockerfile and fly.toml, and .dockerignore

set fly.toml env and vm

[build]
[env]
PORT = "3000" # add this
[http_service]
internal_port = 3000 # ensure that this is same as PORT
force_https = true
auto_stop_machines = true
auto_start_machines = true
min_machines_running = 0
processes = ["app"]
[[vm]]
memory = '256mb'
cpu_kind = 'shared'
cpus = 1

after revised the fly.toml, run flyctl launch --no-deploy again before deploy

flyctl deploy
long scripts
part3\backend>flyctl deploy
==> Verifying app config
Validating part3\backend\fly.toml
✓ Configuration is valid
--> Verified app config
==> Building image
Waiting for remote builder fly-builder-broken-star-6341...
Waiting for remote builder fly-builder-broken-star-6341...
Waiting for remote builder fly-builder-broken-star-6341...
Remote builder fly-builder-broken-star-6341 ready
Waiting for remote builder fly-builder-broken-star-6341...
Waiting for remote builder fly-builder-broken-star-6341...
Waiting for remote builder fly-builder-broken-star-6341...
Remote builder fly-builder-broken-star-6341 ready
==> Building image with Docker
--> docker host: 24.0.7 linux x86_64
[+] Building 35.5s (14/14) FINISHED
=> [internal] load build definition from Dockerfile 1.0s
=> => transferring dockerfile: 864B 1.0s
=> [internal] load .dockerignore 1.0s
=> => transferring context: 368B 1.0s
=> resolve image config for docker.io/docker/dockerfile:1 1.2s
=> docker-image://docker.io/docker/dockerfile:1@sha256:fe40cf4e92cd0c467be2cfc30657a68 0.2s
=> => resolve docker.io/docker/dockerfile:1@sha256:fe40cf4e92cd0c467be2cfc30657a680ae2 0.0s
=> => sha256:dc9e236567481e0aca4c1f52351af213b9a176622f10e3f4a86e5cc48919f 482B / 482B 0.0s
=> => sha256:fd020648a727ee1aa6fe2924bf9c498d19385fa2491ddeecb9da9a499 1.26kB / 1.26kB 0.0s
=> => sha256:2ba8a93af1b3f8d1c5354117c15aa2eaa674a24a81b6622506a8a52 12.46MB / 12.46MB 0.1s
=> => sha256:fe40cf4e92cd0c467be2cfc30657a680ae2398318afd50b0c80585784 8.40kB / 8.40kB 0.0s
=> => extracting sha256:2ba8a93af1b3f8d1c5354117c15aa2eaa674a24a81b6622506a8a524ba8d3f 0.1s
=> [internal] load metadata for docker.io/library/node:21.7.0-slim 1.9s
=> [base 1/2] FROM docker.io/library/node:21.7.0-slim@sha256:fbdb66de323c6aa010c6afc04 2.9s
=> => resolve docker.io/library/node:21.7.0-slim@sha256:fbdb66de323c6aa010c6afc04dda9a 0.0s
=> => sha256:d9f47b780d0151602f95df2e8cb104cbbdc628a688f1eaffba3d99baf 1.37kB / 1.37kB 0.0s
=> => sha256:d58176b808d23800e449d9e89c3cbfcb65f0aa0eb2ef49cbda85d370d 7.62kB / 7.62kB 0.0s
=> => sha256:e1caac4eb9d2ec24aa3618e5992208321a92492aef5fef5eb9e4708 29.12MB / 29.12MB 0.3s
=> => sha256:6e4d260b7fd8f82e7e2c52fe4ad99468397055eb2e489a37dbbcd36ba 3.35kB / 3.35kB 0.0s
=> => sha256:3197b9f5605e8a54053cec13f5b8c756ca734dabf2442306e253886 42.26MB / 42.26MB 1.3s
=> => sha256:b0a37155f3b72deae0c2506d5fcec723bc453136d3b92c2ec8e4221d2 2.70MB / 2.70MB 1.2s
=> => sha256:1e95c4b27d4e131b08e16f58584f5e290ab2e93d8faa37cf00ad31bf4e8b4 454B / 454B 1.0s
=> => sha256:fbdb66de323c6aa010c6afc04dda9a4031d113ebc623588f42633b124 1.21kB / 1.21kB 0.0s
=> => extracting sha256:e1caac4eb9d2ec24aa3618e5992208321a92492aef5fef5eb9e470895f771c 1.2s
=> => extracting sha256:6e4d260b7fd8f82e7e2c52fe4ad99468397055eb2e489a37dbbcd36ba82f93 0.0s
=> => extracting sha256:3197b9f5605e8a54053cec13f5b8c756ca734dabf2442306e253886f8a0753 1.2s
=> => extracting sha256:b0a37155f3b72deae0c2506d5fcec723bc453136d3b92c2ec8e4221d2dfee2 0.1s
=> => extracting sha256:1e95c4b27d4e131b08e16f58584f5e290ab2e93d8faa37cf00ad31bf4e8b4b 0.0s
=> [internal] load build context 0.9s
=> => transferring context: 4.68kB 0.9s
=> [base 2/2] WORKDIR /app 0.1s
=> [build 1/4] RUN apt-get update -qq && apt-get install --no-install-recommends 21.7s
=> [build 2/4] COPY --link package.json ./ 0.0s
=> [build 3/4] RUN npm install 4.4s
=> [build 4/4] COPY --link . . 0.0s
=> [stage-2 1/1] COPY --from=build /app /app 0.1s
=> exporting to image 0.1s
=> => exporting layers 0.1s
=> => writing image sha256:259dfe1338855b59665d4d0ceea3d9391c3a7abc65643b0299634070c93 0.0s
=> => naming to registry.fly.io/backend-fullstackopen-cn:deployment-01J499JTMB6E6639BA 0.0s
--> Building image done
==> Pushing image to fly
The push refers to repository [registry.fly.io/backend-fullstackopen-cn]
dd4b6216804b: Pushed
b5f3ea4f53c9: Pushed
c9ef530f0ff9: Pushed
5dfe06c6e363: Pushed
77596d6aa8be: Pushed
b1cf80d308ef: Pushed
ceb365432eec: Pushed
deployment-01J499JTMB6E6639BA6TBYMJSS: digest: sha256:2c948a0e9c0871ab3ea64fc1b637addc7e211f79
135ec211b4432994f6f6054e size: 1783
--> Pushing image done
image: registry.fly.io/backend-fullstackopen-cn:deployment-01J499JTMB6E6639BA6TBYMJSS
image size: 207 MB
Watch your deployment at https://fly.io/apps/backend-fullstackopen-cn/monitoring
Provisioning ips for backend-fullstackopen-cn
Dedicated ipv6: 2a09:8280:1::3f:4a46:0
Shared ipv4: 66.241.124.178
Add a dedicated ipv4 with: fly ips allocate-v4
This deployment will:
* create 2 "app" machines
No machines in group app, launching a new machine
Creating a second machine to increase service availability
Finished launching new machines
-------
NOTE: The machines for [app] have services with 'auto_stop_machines = "stop"' that will be sto
pped when idling
-------
Checking DNS configuration for backend-fullstackopen-cn.fly.dev
WARN DNS checks failed: read udp 192.168.0.218:64058->8.8.8.8:53: i/o timeout
Visit your newly deployed app at https://backend-fullstackopen-cn.fly.dev/

checked the fly.io web profile, the app is started with 2 machine. try to scale to one machine.

long scripts

https://fly.io/docs/launch/scale-machine/

flyctl status
part3\backend>flyctl status
App
Name = backend-fullstackopen-cn
Owner = personal
Hostname = backend-fullstackopen-cn.fly.dev
Image = backend-fullstackopen-cn:deployment-01J499JTMB6E6639BA6TBYMJSS
Machines
PROCESS ID VERSION REGION STATE ROLE CHECKS LAST UPDATED
app 32871423f631e8 1 lax started 2024-08-02T10:21:53Z
app 4d89013db49d48 1 lax started 2024-08-02T10:22:13Z
part3\backend>flyctl scale show
VM Resources for app: backend-fullstackopen-cn
Groups
NAME COUNT KIND CPUS MEMORY REGIONS
app 2 shared 1 1024 MB lax(2)
part3\backend>flyctl machine status
? Select a machine: [Use arrows to move, type to filter]
> 32871423f631e8 solitary-glitter-5250 (stopped, region lax, process group 'app')
4d89013db49d48 black-sound-6896 (stopped, region lax, process group 'app')
part3\backend>
part3\backend>flyctl machine remove 4d89
Error: could not get machine 4d89: failed to get VM 4d89: invalid machine ID, '4d89' (Request
ID: 01J49A927GFAC3W281J9ENE9KD-nrt)
part3\backend>flyctl machine remove black-sound-6896
Error: could not get machine black-sound-6896: failed to get VM black-sound-6896: invalid mach
ine ID, 'black-sound-6896' (Request ID: 01J49A9V3F48Y0FHE6M8SMXJFP-nrt)
part3\backend>flyctl machine help
Manage Fly Machines. Fly Machines are super-fast, lightweight VMs that can be created, and
then quickly started and stopped as needed with flyctl commands or with the Machines REST
fly.
Usage:
fly machine [command]
Aliases:
machine, machines, m
Available Commands:
api-proxy Establish a proxy to the Machine API through a Wireguard tunnel for local connec
tions
clone Clone a Fly Machine
cordon Deactivate all services on a machine
create Create, but don't start, a machine
destroy Destroy Fly machines
exec Execute a command on a machine
kill Kill (SIGKILL) a Fly machine
leases Manage machine leases
list List Fly machines
restart Restart one or more Fly machines
run Run a machine
start Start one or more Fly machines
status Show current status of a running machine
stop Stop one or more Fly machines
suspend Suspend one or more Fly machines
uncordon Reactivate all services on a machine
update Update a machine
Flags:
-h, --help help for machine
Global Flags:
-t, --access-token string Fly API Access Token
--debug Print additional logs and traces
--verbose Verbose output
Use "fly machine [command] --help" for more information about a command.
part3\backend>flyctl machine status
? Select a machine: 32871423f631e8 solitary-glitter-5250 (stopped, region lax, process group '
app')
Machine ID: 32871423f631e8
Instance ID: 01J499R70X771J4ZBPJKN39C27
State: stopped
VM
ID = 32871423f631e8
Instance ID = 01J499R70X771J4ZBPJKN39C27
State = stopped
Image = backend-fullstackopen-cn:deployment-01J499JTMB6E6639BA6TBYMJSS
Name = solitary-glitter-5250
Private IP = fdaa:0:2f20:a7b:2bf:7ecd:6680:2
Region = lax
Process Group = app
CPU Kind = shared
vCPUs = 1
Memory = 1024
Created = 2024-08-02T10:21:46Z
Updated = 2024-08-02T10:29:10Z
Entrypoint =
Command =
Event Logs
STATE EVENT SOURCE TIMESTAMP INFO
stopped exit flyd 2024-08-02T18:29:10.893+08:00 exit_code=143,oom_killed=false
,requested_stop=true
stopping stop user 2024-08-02T18:29:03.696+08:00
started start flyd 2024-08-02T18:21:53.005+08:00
created launch user 2024-08-02T18:21:46.437+08:00
part3\backend>flyctl machine destroy black-soun-6896
Error: could not get machine black-soun-6896: failed to get VM black-soun-6896: invalid machin
e ID, 'black-soun-6896' (Request ID: 01J49ACNF97ZK1MC1CAJYJ1HHA-nrt)
part3\backend>flyctl machine status
? Select a machine: [Use arrows to move, type to filter]
> 32871423f631e8 solitary-glitter-5250 (stopped, region lax, process group 'app')
4d89013db49d48 black-sound-6896 (stopped, region lax, process group 'app')
part3\backend>flyctl machine destroy black-sound-6896 -f
Error: could not get machine black-sound-6896: failed to get VM black-sound-6896: invalid mach
ine ID, 'black-sound-6896' (Request ID: 01J49AF3T80JHRPJD0GRFE2K2A-nrt)
part3\backend>flyctl machine destroy 4d89013db49d48 -f
machine 4d89013db49d48 was found and is currently in stopped state, attempting to destroy...
4d89013db49d48 has been destroyed
part3\backend>flyctl machine status
? Select a machine: 32871423f631e8 solitary-glitter-5250 (stopped, region lax, process group '
app')
Machine ID: 32871423f631e8
Instance ID: 01J499R70X771J4ZBPJKN39C27
State: stopped
VM
ID = 32871423f631e8
Instance ID = 01J499R70X771J4ZBPJKN39C27
State = stopped
Image = backend-fullstackopen-cn:deployment-01J499JTMB6E6639BA6TBYMJSS
Name = solitary-glitter-5250
Private IP = fdaa:0:2f20:a7b:2bf:7ecd:6680:2
Region = lax
Process Group = app
CPU Kind = shared
vCPUs = 1
Memory = 1024
Created = 2024-08-02T10:21:46Z
Updated = 2024-08-02T10:29:10Z
Entrypoint =
Command =
Event Logs
STATE EVENT SOURCE TIMESTAMP INFO
stopped exit flyd 2024-08-02T18:29:10.893+08:00 exit_code=143,oom_killed=false,requested_stop=true
stopping stop user 2024-08-02T18:29:03.696+08:00
started start flyd 2024-08-02T18:21:53.005+08:00
created launch user 2024-08-02T18:21:46.437+08:00
part3\backend>

finally destroy ed one machine, so this app will run on only one machine(the other not destroy ed)

and scale to 256MB Memory

flyctl scale memory 256

change the fly.toml manually:

[[vm]]
size = 'shared-cpu-1x'
memory = '256mb'
cpu_kind = 'shared'
cpus = 1
flyctl apps open

https://backend-fullstackopen-cn.fly.dev/
https://backend-fullstackopen-cn.fly.dev/api/notes
https://backend-fullstackopen-cn.fly.dev/api/notes/3

It works.

flyctl ping -o personal
ctrl + C
flyctl logs

Whenever you make changes to the application, you can take the new version to production with a command

flyctl deploy

Frontend production build

the vite version of frontend

cd frontend-vite
pnpm build

Serving static files from the backend

cp -r dist ../backend

backend index.js

index.js
app.use(express.static('dist'))

The application can now be used from the backend address http://localhost:3001

frontend services/notes.js

change baseUrl to relative, we have already done.

Because here I put the proxy section on the upper position.

import axios from 'axios'
const baseUrl = '/api/notes'
const getAll = () => {
const request = axios.get(baseUrl)
return request.then(response => response.data)
}
// ...

The application can now be used from the backend address http://localhost:3001

Our application now works exactly like the single-page app example application we studied in part 0.

The whole app to the internet

flyctl deploy

The application works perfectly, except we haven’t added the functionality for changing the importance of a note to the backend yet.

NOTE: When using Fly.io, be aware that the .dockerignore file in your project directory lists files not uploaded during deployment. The dist directory is included by default. To deploy this directory, remove its reference from the .dockerignore file, ensuring your app is get properly deployed.

NOTE: changing the importance DOES NOT work yet since the backend has no implementation for it yet.

Our application saves the notes to a variable. If the application crashes or is restarted, all of the data will disappear.

The application needs a database. We will do it later

Streamlining deploying of the frontend

__Be careful of the folder position in the build:ui section __

{
"scripts": {
// ...
"build:ui": "rm -rf dist && cd ../notes-frontend/ && npm run build && cp -r dist ../notes-backend",
"deploy": "fly deploy",
"deploy:full": "npm run build:ui && npm run deploy",
"logs:prod": "fly logs"
}
}

Note for Windows users

"build:ui": "@powershell Remove-Item -Recurse -Force dist && cd ../frontend && npm run build && @powershell Copy-Item dist -Recurse ../backend",

If the script does not work on Windows, confirm that you are using Powershell and not Command Prompt. If you have installed Git Bash or another Linux-like terminal, you may be able to run Linux-like commands on Windows as well.

flyctl deploy

The end of part3b main content

exercises 3.9 - 3.11

3.9 Phonebook backend step 9

combine backend and frontend in one folder

3.10 Phonebook backend step 10

Deploy the backend to internet(fly.io or render)

3.11 Full Stack Phonebook

My solutions

My solutions:
(Please complete your own solutions before click here.)

3.9
3.10
3.11

frontend/services/persons.jsx

const baseUrl = "/api/persons"

backend:

pnpm i cors
backend index.js
// index.js
const cors = require("cors");
app.use(cors());
app.use(express.json());
app.use(express.static('dist'))
index.js
const PORT = process.env.PORT || 3001
app.listen(PORT, () => {
console.log(`Server running on port ${PORT}`)
})

proxy:

frontend vite.config.js

vite.config.js
import { defineConfig } from "vite";
import react from "@vitejs/plugin-react";
// https://vitejs.dev/config/
export default defineConfig({
plugins: [react()],
server: {
proxy: {
"/api": {
target: "http://localhost:3001",
changeOrigin: true,
},
},
},
});

fly.io deploy by cli or render deploy from git

Visit your newly deployed app at https://backend-fullstackopen-phonebook.fly.dev/

pnpm build on frontend

build:ui etc scripts on backend

the whole app deploy to internet

Homepage at / blank, caused by the frontend error require:

// var _ = require('lodash')
import _ from 'lodash'

rerun build:ui and deploy, every works now.