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.
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:
pnpm i cors
revise backend 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:
const baseUrl = "/api/notes";
Change the vite.config.js, add the proxy beforehand.
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:
const PORT = process.env.PORT || 3001app.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 loginstuck at Waiting for session...⣷
flyctl auth signup --verbose | tee tempOpening https://fly.io/app/auth/cli/...Login in the opened browsersuccessfully logged in as ...
flyctl launch --no-deployYopened a browser, change name and region, confirm
...
Waiting for launch data... DoneCreated app 'backend-fullstackopen-cn' in organization 'personal'Admin URL: https://fly.io/apps/backend-fullstackopen-cnHostname: backend-fullstackopen-cn.fly.devinstalling: npx --yes @flydotio/dockerfile@latest create DockerfileWrote config file fly.tomlValidating 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 configValidating part3\backend\fly.toml✓ Configuration is valid--> Verified app config==> Building imageWaiting 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 readyWaiting 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 flyThe push refers to repository [registry.fly.io/backend-fullstackopen-cn]dd4b6216804b: Pushedb5f3ea4f53c9: Pushedc9ef530f0ff9: Pushed5dfe06c6e363: Pushed77596d6aa8be: Pushedb1cf80d308ef: Pushedceb365432eec: Pusheddeployment-01J499JTMB6E6639BA6TBYMJSS: digest: sha256:2c948a0e9c0871ab3ea64fc1b637addc7e211f79135ec211b4432994f6f6054e size: 1783--> Pushing image doneimage: registry.fly.io/backend-fullstackopen-cn:deployment-01J499JTMB6E6639BA6TBYMJSSimage 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 machineCreating a second machine to increase service availabilityFinished launching new machines-------NOTE: The machines for [app] have services with 'auto_stop_machines = "stop"' that will be stopped when idling
-------Checking DNS configuration for backend-fullstackopen-cn.fly.devWARN 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 statusApp Name = backend-fullstackopen-cn Owner = personal Hostname = backend-fullstackopen-cn.fly.dev Image = backend-fullstackopen-cn:deployment-01J499JTMB6E6639BA6TBYMJSS
MachinesPROCESS ID VERSION REGION STATE ROLE CHECKS LAST UPDATEDapp 32871423f631e8 1 lax started 2024-08-02T10:21:53Zapp 4d89013db49d48 1 lax started 2024-08-02T10:22:13Z
part3\backend>flyctl scale showVM Resources for app: backend-fullstackopen-cn
GroupsNAME COUNT KIND CPUS MEMORY REGIONSapp 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 4d89Error: could not get machine 4d89: failed to get VM 4d89: invalid machine ID, '4d89' (RequestID: 01J49A927GFAC3W281J9ENE9KD-nrt)
part3\backend>flyctl machine remove black-sound-6896Error: could not get machine black-sound-6896: failed to get VM black-sound-6896: invalid machine ID, 'black-sound-6896' (Request ID: 01J49A9V3F48Y0FHE6M8SMXJFP-nrt)
part3\backend>flyctl machine helpManage Fly Machines. Fly Machines are super-fast, lightweight VMs that can be created, andthen quickly started and stopped as needed with flyctl commands or with the Machines RESTfly.
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 connections 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: 32871423f631e8Instance ID: 01J499R70X771J4ZBPJKN39C27State: 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 LogsSTATE EVENT SOURCE TIMESTAMP INFO
stopped exit flyd 2024-08-02T18:29:10.893+08:00 exit_code=143,oom_killed=false,requested_stop=truestopping stop user 2024-08-02T18:29:03.696+08:00started start flyd 2024-08-02T18:21:53.005+08:00created launch user 2024-08-02T18:21:46.437+08:00
part3\backend>flyctl machine destroy black-soun-6896Error: could not get machine black-soun-6896: failed to get VM black-soun-6896: invalid machine 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 -fError: could not get machine black-sound-6896: failed to get VM black-sound-6896: invalid machine ID, 'black-sound-6896' (Request ID: 01J49AF3T80JHRPJD0GRFE2K2A-nrt)
part3\backend>flyctl machine destroy 4d89013db49d48 -fmachine 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: 32871423f631e8Instance ID: 01J499R70X771J4ZBPJKN39C27State: 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 LogsSTATE EVENT SOURCE TIMESTAMP INFOstopped exit flyd 2024-08-02T18:29:10.893+08:00 exit_code=143,oom_killed=false,requested_stop=truestopping stop user 2024-08-02T18:29:03.696+08:00started start flyd 2024-08-02T18:21:53.005+08:00created 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 personalctrl + 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-vitepnpm build
Serving static files from the backend
cp -r dist ../backend
backend 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
// index.js
const cors = require("cors");
app.use(cors());app.use(express.json());app.use(express.static('dist'))
const PORT = process.env.PORT || 3001app.listen(PORT, () => { console.log(`Server running on port ${PORT}`)})
proxy:
frontend 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.