├── .dockerignore ├── .gitignore ├── Dockerfile ├── LICENSE ├── README.md ├── backend ├── app │ ├── __init__.py │ ├── app.py │ └── routes │ │ ├── __init__.py │ │ └── api.py ├── main.py ├── poetry.lock └── pyproject.toml ├── docker └── config.json └── frontend ├── index.html ├── package.json ├── pnpm-lock.yaml ├── public └── favicon.ico ├── src ├── App.vue └── main.js └── vite.config.js /.dockerignore: -------------------------------------------------------------------------------- 1 | .git/ 2 | .DS_Store/ 3 | .vscode/ 4 | .idea/ 5 | 6 | venv/ 7 | .venv/ 8 | node_modules/ 9 | dist/ 10 | build/ 11 | 12 | __pycache__/ 13 | *.pyc 14 | 15 | *.log* 16 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store/ 2 | .vscode/ 3 | .idea/ 4 | 5 | venv/ 6 | .venv/ 7 | node_modules/ 8 | 9 | __pycache__/ 10 | *.pyc 11 | *.log* 12 | 13 | dist/ 14 | build/ 15 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM docker.io/python:3.11 as build-backend 2 | 3 | ENV PIP_NO_CACHE_DIR=1 \ 4 | PIP_ROOT_USER_ACTION=ignore \ 5 | POETRY_VIRTUALENVS_IN_PROJECT=true 6 | 7 | RUN pip install -U pip setuptools wheel -q && \ 8 | pip install poetry==1.6.1 -q 9 | 10 | WORKDIR /app/backend 11 | 12 | COPY backend/pyproject.toml backend/poetry.lock ./ 13 | RUN poetry install --only main --no-root --sync --no-cache 14 | COPY backend/app/ app/ 15 | 16 | 17 | FROM docker.io/node:18 as build-frontend 18 | 19 | ENV npm_config_update_notifier=false 20 | 21 | RUN corepack enable 22 | 23 | WORKDIR /app/frontend 24 | 25 | COPY frontend/package.json frontend/pnpm-lock.yaml ./ 26 | RUN pnpm fetch 27 | 28 | COPY frontend/*.config.js frontend/index.html ./ 29 | COPY frontend/src src/ 30 | COPY frontend/public public/ 31 | 32 | RUN pnpm install 33 | RUN pnpm build 34 | 35 | 36 | FROM docker.io/nginx/unit:1.29.1-python3.11 37 | 38 | WORKDIR /app 39 | 40 | COPY --from=build-backend /app/backend backend 41 | COPY --from=build-frontend /app/frontend/dist frontend 42 | 43 | COPY docker/config.json /docker-entrypoint.d/config.json 44 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright © 2022 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | 5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | 7 | THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # nginx-fastapi-vue-docker 2 | 3 | Example application for running a web application with [Vue.js](https://vuejs.org/) 4 | as a frontend and [FastAPI](https://fastapi.tiangolo.com/) as a backend using nginx 5 | in a single docker image and container. 6 | 7 | To allow for a single image, [nginx unit](https://unit.nginx.org/) is used to 8 | pass requests directly to the asgi application. 9 | 10 | ## Development 11 | 12 | The `backend` folder contains a [Python Poetry](https://python-poetry.org/) project 13 | using the FastAPI framework. Use the following commands to start developing. 14 | 15 | ```shell 16 | cd backend 17 | poetry install 18 | poetry run uvicorn app:app --debug --reload 19 | ``` 20 | 21 | The `frontend` folder contains a [Pnpm](https://pnpm.io/) project using the 22 | Vue.js framework. Use the following commands to start developing. 23 | 24 | ```shell 25 | cd frontend 26 | pnpm install 27 | pnpm dev 28 | ``` 29 | 30 | After both the frontend and backend are up, you can visit http://localhost:8080/ to 31 | view the app. 32 | 33 | ## Configuration 34 | To configure nginx-unit, modify the `docker/config.json` file using the provided 35 | [guide](https://unit.nginx.org/configuration/). 36 | 37 | ## Building 38 | The docker build takes advantage of multi-stage builds, so docker 17.05+ is needed. 39 | 40 | To build, simply run 41 | ```shell 42 | docker build . -t nginx-fastapi-vue-docker 43 | ``` 44 | 45 | Then to run, use 46 | ```shell 47 | docker run --rm -p 80:80 nginx-fastapi-vue-docker 48 | ``` 49 | 50 | You now be able to open http://localhost/ and see your application. 51 | -------------------------------------------------------------------------------- /backend/app/__init__.py: -------------------------------------------------------------------------------- 1 | from .app import app 2 | 3 | __all__ = [ 4 | "app", 5 | ] 6 | -------------------------------------------------------------------------------- /backend/app/app.py: -------------------------------------------------------------------------------- 1 | from fastapi import FastAPI 2 | 3 | from .routes import api 4 | 5 | app = FastAPI( 6 | openapi_url="/api/openapi.json", 7 | docs_url="/api/docs", 8 | redoc_url="/api/redoc", 9 | ) 10 | 11 | app.include_router(api, prefix="/api") 12 | -------------------------------------------------------------------------------- /backend/app/routes/__init__.py: -------------------------------------------------------------------------------- 1 | from .api import api 2 | 3 | __all__ = [ 4 | "api", 5 | ] 6 | -------------------------------------------------------------------------------- /backend/app/routes/api.py: -------------------------------------------------------------------------------- 1 | import asyncio 2 | 3 | from fastapi import APIRouter 4 | from pydantic import BaseModel 5 | 6 | api = APIRouter() 7 | 8 | 9 | class Message(BaseModel): 10 | message: str 11 | 12 | 13 | @api.get("/hello", response_model=Message) 14 | async def hello(): 15 | await asyncio.sleep(0.5) 16 | return Message(message="Hello, world!") 17 | -------------------------------------------------------------------------------- /backend/main.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | import uvicorn 3 | 4 | if __name__ == "__main__": 5 | uvicorn.run("app:app", reload=True, debug=True) 6 | -------------------------------------------------------------------------------- /backend/poetry.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Poetry 1.6.1 and should not be changed by hand. 2 | 3 | [[package]] 4 | name = "annotated-types" 5 | version = "0.5.0" 6 | description = "Reusable constraint types to use with typing.Annotated" 7 | optional = false 8 | python-versions = ">=3.7" 9 | files = [ 10 | {file = "annotated_types-0.5.0-py3-none-any.whl", hash = "sha256:58da39888f92c276ad970249761ebea80ba544b77acddaa1a4d6cf78287d45fd"}, 11 | {file = "annotated_types-0.5.0.tar.gz", hash = "sha256:47cdc3490d9ac1506ce92c7aaa76c579dc3509ff11e098fc867e5130ab7be802"}, 12 | ] 13 | 14 | [[package]] 15 | name = "anyio" 16 | version = "3.7.1" 17 | description = "High level compatibility layer for multiple asynchronous event loop implementations" 18 | optional = false 19 | python-versions = ">=3.7" 20 | files = [ 21 | {file = "anyio-3.7.1-py3-none-any.whl", hash = "sha256:91dee416e570e92c64041bd18b900d1d6fa78dff7048769ce5ac5ddad004fbb5"}, 22 | {file = "anyio-3.7.1.tar.gz", hash = "sha256:44a3c9aba0f5defa43261a8b3efb97891f2bd7d804e0e1f56419befa1adfc780"}, 23 | ] 24 | 25 | [package.dependencies] 26 | idna = ">=2.8" 27 | sniffio = ">=1.1" 28 | 29 | [package.extras] 30 | doc = ["Sphinx", "packaging", "sphinx-autodoc-typehints (>=1.2.0)", "sphinx-rtd-theme (>=1.2.2)", "sphinxcontrib-jquery"] 31 | test = ["anyio[trio]", "coverage[toml] (>=4.5)", "hypothesis (>=4.0)", "mock (>=4)", "psutil (>=5.9)", "pytest (>=7.0)", "pytest-mock (>=3.6.1)", "trustme", "uvloop (>=0.17)"] 32 | trio = ["trio (<0.22)"] 33 | 34 | [[package]] 35 | name = "click" 36 | version = "8.1.7" 37 | description = "Composable command line interface toolkit" 38 | optional = false 39 | python-versions = ">=3.7" 40 | files = [ 41 | {file = "click-8.1.7-py3-none-any.whl", hash = "sha256:ae74fb96c20a0277a1d615f1e4d73c8414f5a98db8b799a7931d1582f3390c28"}, 42 | {file = "click-8.1.7.tar.gz", hash = "sha256:ca9853ad459e787e2192211578cc907e7594e294c7ccc834310722b41b9ca6de"}, 43 | ] 44 | 45 | [package.dependencies] 46 | colorama = {version = "*", markers = "platform_system == \"Windows\""} 47 | 48 | [[package]] 49 | name = "colorama" 50 | version = "0.4.6" 51 | description = "Cross-platform colored terminal text." 52 | optional = false 53 | python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" 54 | files = [ 55 | {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, 56 | {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, 57 | ] 58 | 59 | [[package]] 60 | name = "fastapi" 61 | version = "0.103.2" 62 | description = "FastAPI framework, high performance, easy to learn, fast to code, ready for production" 63 | optional = false 64 | python-versions = ">=3.7" 65 | files = [ 66 | {file = "fastapi-0.103.2-py3-none-any.whl", hash = "sha256:3270de872f0fe9ec809d4bd3d4d890c6d5cc7b9611d721d6438f9dacc8c4ef2e"}, 67 | {file = "fastapi-0.103.2.tar.gz", hash = "sha256:75a11f6bfb8fc4d2bec0bd710c2d5f2829659c0e8c0afd5560fdda6ce25ec653"}, 68 | ] 69 | 70 | [package.dependencies] 71 | anyio = ">=3.7.1,<4.0.0" 72 | pydantic = ">=1.7.4,<1.8 || >1.8,<1.8.1 || >1.8.1,<2.0.0 || >2.0.0,<2.0.1 || >2.0.1,<2.1.0 || >2.1.0,<3.0.0" 73 | starlette = ">=0.27.0,<0.28.0" 74 | typing-extensions = ">=4.5.0" 75 | 76 | [package.extras] 77 | all = ["email-validator (>=2.0.0)", "httpx (>=0.23.0)", "itsdangerous (>=1.1.0)", "jinja2 (>=2.11.2)", "orjson (>=3.2.1)", "pydantic-extra-types (>=2.0.0)", "pydantic-settings (>=2.0.0)", "python-multipart (>=0.0.5)", "pyyaml (>=5.3.1)", "ujson (>=4.0.1,!=4.0.2,!=4.1.0,!=4.2.0,!=4.3.0,!=5.0.0,!=5.1.0)", "uvicorn[standard] (>=0.12.0)"] 78 | 79 | [[package]] 80 | name = "h11" 81 | version = "0.14.0" 82 | description = "A pure-Python, bring-your-own-I/O implementation of HTTP/1.1" 83 | optional = false 84 | python-versions = ">=3.7" 85 | files = [ 86 | {file = "h11-0.14.0-py3-none-any.whl", hash = "sha256:e3fe4ac4b851c468cc8363d500db52c2ead036020723024a109d37346efaa761"}, 87 | {file = "h11-0.14.0.tar.gz", hash = "sha256:8f19fbbe99e72420ff35c00b27a34cb9937e902a8b810e2c88300c6f0a3b699d"}, 88 | ] 89 | 90 | [[package]] 91 | name = "idna" 92 | version = "3.4" 93 | description = "Internationalized Domain Names in Applications (IDNA)" 94 | optional = false 95 | python-versions = ">=3.5" 96 | files = [ 97 | {file = "idna-3.4-py3-none-any.whl", hash = "sha256:90b77e79eaa3eba6de819a0c442c0b4ceefc341a7a2ab77d7562bf49f425c5c2"}, 98 | {file = "idna-3.4.tar.gz", hash = "sha256:814f528e8dead7d329833b91c5faa87d60bf71824cd12a7530b5526063d02cb4"}, 99 | ] 100 | 101 | [[package]] 102 | name = "pydantic" 103 | version = "2.4.2" 104 | description = "Data validation using Python type hints" 105 | optional = false 106 | python-versions = ">=3.7" 107 | files = [ 108 | {file = "pydantic-2.4.2-py3-none-any.whl", hash = "sha256:bc3ddf669d234f4220e6e1c4d96b061abe0998185a8d7855c0126782b7abc8c1"}, 109 | {file = "pydantic-2.4.2.tar.gz", hash = "sha256:94f336138093a5d7f426aac732dcfe7ab4eb4da243c88f891d65deb4a2556ee7"}, 110 | ] 111 | 112 | [package.dependencies] 113 | annotated-types = ">=0.4.0" 114 | pydantic-core = "2.10.1" 115 | typing-extensions = ">=4.6.1" 116 | 117 | [package.extras] 118 | email = ["email-validator (>=2.0.0)"] 119 | 120 | [[package]] 121 | name = "pydantic-core" 122 | version = "2.10.1" 123 | description = "" 124 | optional = false 125 | python-versions = ">=3.7" 126 | files = [ 127 | {file = "pydantic_core-2.10.1-cp310-cp310-macosx_10_7_x86_64.whl", hash = "sha256:d64728ee14e667ba27c66314b7d880b8eeb050e58ffc5fec3b7a109f8cddbd63"}, 128 | {file = "pydantic_core-2.10.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:48525933fea744a3e7464c19bfede85df4aba79ce90c60b94d8b6e1eddd67096"}, 129 | {file = "pydantic_core-2.10.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ef337945bbd76cce390d1b2496ccf9f90b1c1242a3a7bc242ca4a9fc5993427a"}, 130 | {file = "pydantic_core-2.10.1-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:a1392e0638af203cee360495fd2cfdd6054711f2db5175b6e9c3c461b76f5175"}, 131 | {file = "pydantic_core-2.10.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0675ba5d22de54d07bccde38997e780044dcfa9a71aac9fd7d4d7a1d2e3e65f7"}, 132 | {file = "pydantic_core-2.10.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:128552af70a64660f21cb0eb4876cbdadf1a1f9d5de820fed6421fa8de07c893"}, 133 | {file = "pydantic_core-2.10.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8f6e6aed5818c264412ac0598b581a002a9f050cb2637a84979859e70197aa9e"}, 134 | {file = "pydantic_core-2.10.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:ecaac27da855b8d73f92123e5f03612b04c5632fd0a476e469dfc47cd37d6b2e"}, 135 | {file = "pydantic_core-2.10.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:b3c01c2fb081fced3bbb3da78510693dc7121bb893a1f0f5f4b48013201f362e"}, 136 | {file = "pydantic_core-2.10.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:92f675fefa977625105708492850bcbc1182bfc3e997f8eecb866d1927c98ae6"}, 137 | {file = "pydantic_core-2.10.1-cp310-none-win32.whl", hash = "sha256:420a692b547736a8d8703c39ea935ab5d8f0d2573f8f123b0a294e49a73f214b"}, 138 | {file = "pydantic_core-2.10.1-cp310-none-win_amd64.whl", hash = "sha256:0880e239827b4b5b3e2ce05e6b766a7414e5f5aedc4523be6b68cfbc7f61c5d0"}, 139 | {file = "pydantic_core-2.10.1-cp311-cp311-macosx_10_7_x86_64.whl", hash = "sha256:073d4a470b195d2b2245d0343569aac7e979d3a0dcce6c7d2af6d8a920ad0bea"}, 140 | {file = "pydantic_core-2.10.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:600d04a7b342363058b9190d4e929a8e2e715c5682a70cc37d5ded1e0dd370b4"}, 141 | {file = "pydantic_core-2.10.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:39215d809470f4c8d1881758575b2abfb80174a9e8daf8f33b1d4379357e417c"}, 142 | {file = "pydantic_core-2.10.1-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:eeb3d3d6b399ffe55f9a04e09e635554012f1980696d6b0aca3e6cf42a17a03b"}, 143 | {file = "pydantic_core-2.10.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a7a7902bf75779bc12ccfc508bfb7a4c47063f748ea3de87135d433a4cca7a2f"}, 144 | {file = "pydantic_core-2.10.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3625578b6010c65964d177626fde80cf60d7f2e297d56b925cb5cdeda6e9925a"}, 145 | {file = "pydantic_core-2.10.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:caa48fc31fc7243e50188197b5f0c4228956f97b954f76da157aae7f67269ae8"}, 146 | {file = "pydantic_core-2.10.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:07ec6d7d929ae9c68f716195ce15e745b3e8fa122fc67698ac6498d802ed0fa4"}, 147 | {file = "pydantic_core-2.10.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:e6f31a17acede6a8cd1ae2d123ce04d8cca74056c9d456075f4f6f85de055607"}, 148 | {file = "pydantic_core-2.10.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:d8f1ebca515a03e5654f88411420fea6380fc841d1bea08effb28184e3d4899f"}, 149 | {file = "pydantic_core-2.10.1-cp311-none-win32.whl", hash = "sha256:6db2eb9654a85ada248afa5a6db5ff1cf0f7b16043a6b070adc4a5be68c716d6"}, 150 | {file = "pydantic_core-2.10.1-cp311-none-win_amd64.whl", hash = "sha256:4a5be350f922430997f240d25f8219f93b0c81e15f7b30b868b2fddfc2d05f27"}, 151 | {file = "pydantic_core-2.10.1-cp311-none-win_arm64.whl", hash = "sha256:5fdb39f67c779b183b0c853cd6b45f7db84b84e0571b3ef1c89cdb1dfc367325"}, 152 | {file = "pydantic_core-2.10.1-cp312-cp312-macosx_10_7_x86_64.whl", hash = "sha256:b1f22a9ab44de5f082216270552aa54259db20189e68fc12484873d926426921"}, 153 | {file = "pydantic_core-2.10.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8572cadbf4cfa95fb4187775b5ade2eaa93511f07947b38f4cd67cf10783b118"}, 154 | {file = "pydantic_core-2.10.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:db9a28c063c7c00844ae42a80203eb6d2d6bbb97070cfa00194dff40e6f545ab"}, 155 | {file = "pydantic_core-2.10.1-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:0e2a35baa428181cb2270a15864ec6286822d3576f2ed0f4cd7f0c1708472aff"}, 156 | {file = "pydantic_core-2.10.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:05560ab976012bf40f25d5225a58bfa649bb897b87192a36c6fef1ab132540d7"}, 157 | {file = "pydantic_core-2.10.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d6495008733c7521a89422d7a68efa0a0122c99a5861f06020ef5b1f51f9ba7c"}, 158 | {file = "pydantic_core-2.10.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:14ac492c686defc8e6133e3a2d9eaf5261b3df26b8ae97450c1647286750b901"}, 159 | {file = "pydantic_core-2.10.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:8282bab177a9a3081fd3d0a0175a07a1e2bfb7fcbbd949519ea0980f8a07144d"}, 160 | {file = "pydantic_core-2.10.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:aafdb89fdeb5fe165043896817eccd6434aee124d5ee9b354f92cd574ba5e78f"}, 161 | {file = "pydantic_core-2.10.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:f6defd966ca3b187ec6c366604e9296f585021d922e666b99c47e78738b5666c"}, 162 | {file = "pydantic_core-2.10.1-cp312-none-win32.whl", hash = "sha256:7c4d1894fe112b0864c1fa75dffa045720a194b227bed12f4be7f6045b25209f"}, 163 | {file = "pydantic_core-2.10.1-cp312-none-win_amd64.whl", hash = "sha256:5994985da903d0b8a08e4935c46ed8daf5be1cf217489e673910951dc533d430"}, 164 | {file = "pydantic_core-2.10.1-cp312-none-win_arm64.whl", hash = "sha256:0d8a8adef23d86d8eceed3e32e9cca8879c7481c183f84ed1a8edc7df073af94"}, 165 | {file = "pydantic_core-2.10.1-cp37-cp37m-macosx_10_7_x86_64.whl", hash = "sha256:9badf8d45171d92387410b04639d73811b785b5161ecadabf056ea14d62d4ede"}, 166 | {file = "pydantic_core-2.10.1-cp37-cp37m-macosx_11_0_arm64.whl", hash = "sha256:ebedb45b9feb7258fac0a268a3f6bec0a2ea4d9558f3d6f813f02ff3a6dc6698"}, 167 | {file = "pydantic_core-2.10.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cfe1090245c078720d250d19cb05d67e21a9cd7c257698ef139bc41cf6c27b4f"}, 168 | {file = "pydantic_core-2.10.1-cp37-cp37m-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e357571bb0efd65fd55f18db0a2fb0ed89d0bb1d41d906b138f088933ae618bb"}, 169 | {file = "pydantic_core-2.10.1-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b3dcd587b69bbf54fc04ca157c2323b8911033e827fffaecf0cafa5a892a0904"}, 170 | {file = "pydantic_core-2.10.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9c120c9ce3b163b985a3b966bb701114beb1da4b0468b9b236fc754783d85aa3"}, 171 | {file = "pydantic_core-2.10.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:15d6bca84ffc966cc9976b09a18cf9543ed4d4ecbd97e7086f9ce9327ea48891"}, 172 | {file = "pydantic_core-2.10.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:5cabb9710f09d5d2e9e2748c3e3e20d991a4c5f96ed8f1132518f54ab2967221"}, 173 | {file = "pydantic_core-2.10.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:82f55187a5bebae7d81d35b1e9aaea5e169d44819789837cdd4720d768c55d15"}, 174 | {file = "pydantic_core-2.10.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:1d40f55222b233e98e3921df7811c27567f0e1a4411b93d4c5c0f4ce131bc42f"}, 175 | {file = "pydantic_core-2.10.1-cp37-none-win32.whl", hash = "sha256:14e09ff0b8fe6e46b93d36a878f6e4a3a98ba5303c76bb8e716f4878a3bee92c"}, 176 | {file = "pydantic_core-2.10.1-cp37-none-win_amd64.whl", hash = "sha256:1396e81b83516b9d5c9e26a924fa69164156c148c717131f54f586485ac3c15e"}, 177 | {file = "pydantic_core-2.10.1-cp38-cp38-macosx_10_7_x86_64.whl", hash = "sha256:6835451b57c1b467b95ffb03a38bb75b52fb4dc2762bb1d9dbed8de31ea7d0fc"}, 178 | {file = "pydantic_core-2.10.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:b00bc4619f60c853556b35f83731bd817f989cba3e97dc792bb8c97941b8053a"}, 179 | {file = "pydantic_core-2.10.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0fa467fd300a6f046bdb248d40cd015b21b7576c168a6bb20aa22e595c8ffcdd"}, 180 | {file = "pydantic_core-2.10.1-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d99277877daf2efe074eae6338453a4ed54a2d93fb4678ddfe1209a0c93a2468"}, 181 | {file = "pydantic_core-2.10.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fa7db7558607afeccb33c0e4bf1c9a9a835e26599e76af6fe2fcea45904083a6"}, 182 | {file = "pydantic_core-2.10.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:aad7bd686363d1ce4ee930ad39f14e1673248373f4a9d74d2b9554f06199fb58"}, 183 | {file = "pydantic_core-2.10.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:443fed67d33aa85357464f297e3d26e570267d1af6fef1c21ca50921d2976302"}, 184 | {file = "pydantic_core-2.10.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:042462d8d6ba707fd3ce9649e7bf268633a41018d6a998fb5fbacb7e928a183e"}, 185 | {file = "pydantic_core-2.10.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:ecdbde46235f3d560b18be0cb706c8e8ad1b965e5c13bbba7450c86064e96561"}, 186 | {file = "pydantic_core-2.10.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:ed550ed05540c03f0e69e6d74ad58d026de61b9eaebebbaaf8873e585cbb18de"}, 187 | {file = "pydantic_core-2.10.1-cp38-none-win32.whl", hash = "sha256:8cdbbd92154db2fec4ec973d45c565e767ddc20aa6dbaf50142676484cbff8ee"}, 188 | {file = "pydantic_core-2.10.1-cp38-none-win_amd64.whl", hash = "sha256:9f6f3e2598604956480f6c8aa24a3384dbf6509fe995d97f6ca6103bb8c2534e"}, 189 | {file = "pydantic_core-2.10.1-cp39-cp39-macosx_10_7_x86_64.whl", hash = "sha256:655f8f4c8d6a5963c9a0687793da37b9b681d9ad06f29438a3b2326d4e6b7970"}, 190 | {file = "pydantic_core-2.10.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:e570ffeb2170e116a5b17e83f19911020ac79d19c96f320cbfa1fa96b470185b"}, 191 | {file = "pydantic_core-2.10.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:64322bfa13e44c6c30c518729ef08fda6026b96d5c0be724b3c4ae4da939f875"}, 192 | {file = "pydantic_core-2.10.1-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:485a91abe3a07c3a8d1e082ba29254eea3e2bb13cbbd4351ea4e5a21912cc9b0"}, 193 | {file = "pydantic_core-2.10.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f7c2b8eb9fc872e68b46eeaf835e86bccc3a58ba57d0eedc109cbb14177be531"}, 194 | {file = "pydantic_core-2.10.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a5cb87bdc2e5f620693148b5f8f842d293cae46c5f15a1b1bf7ceeed324a740c"}, 195 | {file = "pydantic_core-2.10.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:25bd966103890ccfa028841a8f30cebcf5875eeac8c4bde4fe221364c92f0c9a"}, 196 | {file = "pydantic_core-2.10.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:f323306d0556351735b54acbf82904fe30a27b6a7147153cbe6e19aaaa2aa429"}, 197 | {file = "pydantic_core-2.10.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:0c27f38dc4fbf07b358b2bc90edf35e82d1703e22ff2efa4af4ad5de1b3833e7"}, 198 | {file = "pydantic_core-2.10.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:f1365e032a477c1430cfe0cf2856679529a2331426f8081172c4a74186f1d595"}, 199 | {file = "pydantic_core-2.10.1-cp39-none-win32.whl", hash = "sha256:a1c311fd06ab3b10805abb72109f01a134019739bd3286b8ae1bc2fc4e50c07a"}, 200 | {file = "pydantic_core-2.10.1-cp39-none-win_amd64.whl", hash = "sha256:ae8a8843b11dc0b03b57b52793e391f0122e740de3df1474814c700d2622950a"}, 201 | {file = "pydantic_core-2.10.1-pp310-pypy310_pp73-macosx_10_7_x86_64.whl", hash = "sha256:d43002441932f9a9ea5d6f9efaa2e21458221a3a4b417a14027a1d530201ef1b"}, 202 | {file = "pydantic_core-2.10.1-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:fcb83175cc4936a5425dde3356f079ae03c0802bbdf8ff82c035f8a54b333521"}, 203 | {file = "pydantic_core-2.10.1-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:962ed72424bf1f72334e2f1e61b68f16c0e596f024ca7ac5daf229f7c26e4208"}, 204 | {file = "pydantic_core-2.10.1-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2cf5bb4dd67f20f3bbc1209ef572a259027c49e5ff694fa56bed62959b41e1f9"}, 205 | {file = "pydantic_core-2.10.1-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:e544246b859f17373bed915182ab841b80849ed9cf23f1f07b73b7c58baee5fb"}, 206 | {file = "pydantic_core-2.10.1-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:c0877239307b7e69d025b73774e88e86ce82f6ba6adf98f41069d5b0b78bd1bf"}, 207 | {file = "pydantic_core-2.10.1-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:53df009d1e1ba40f696f8995683e067e3967101d4bb4ea6f667931b7d4a01357"}, 208 | {file = "pydantic_core-2.10.1-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:a1254357f7e4c82e77c348dabf2d55f1d14d19d91ff025004775e70a6ef40ada"}, 209 | {file = "pydantic_core-2.10.1-pp37-pypy37_pp73-macosx_10_7_x86_64.whl", hash = "sha256:524ff0ca3baea164d6d93a32c58ac79eca9f6cf713586fdc0adb66a8cdeab96a"}, 210 | {file = "pydantic_core-2.10.1-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3f0ac9fb8608dbc6eaf17956bf623c9119b4db7dbb511650910a82e261e6600f"}, 211 | {file = "pydantic_core-2.10.1-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:320f14bd4542a04ab23747ff2c8a778bde727158b606e2661349557f0770711e"}, 212 | {file = "pydantic_core-2.10.1-pp37-pypy37_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:63974d168b6233b4ed6a0046296803cb13c56637a7b8106564ab575926572a55"}, 213 | {file = "pydantic_core-2.10.1-pp37-pypy37_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:417243bf599ba1f1fef2bb8c543ceb918676954734e2dcb82bf162ae9d7bd514"}, 214 | {file = "pydantic_core-2.10.1-pp37-pypy37_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:dda81e5ec82485155a19d9624cfcca9be88a405e2857354e5b089c2a982144b2"}, 215 | {file = "pydantic_core-2.10.1-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:14cfbb00959259e15d684505263d5a21732b31248a5dd4941f73a3be233865b9"}, 216 | {file = "pydantic_core-2.10.1-pp38-pypy38_pp73-macosx_10_7_x86_64.whl", hash = "sha256:631cb7415225954fdcc2a024119101946793e5923f6c4d73a5914d27eb3d3a05"}, 217 | {file = "pydantic_core-2.10.1-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:bec7dd208a4182e99c5b6c501ce0b1f49de2802448d4056091f8e630b28e9a52"}, 218 | {file = "pydantic_core-2.10.1-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:149b8a07712f45b332faee1a2258d8ef1fb4a36f88c0c17cb687f205c5dc6e7d"}, 219 | {file = "pydantic_core-2.10.1-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4d966c47f9dd73c2d32a809d2be529112d509321c5310ebf54076812e6ecd884"}, 220 | {file = "pydantic_core-2.10.1-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:7eb037106f5c6b3b0b864ad226b0b7ab58157124161d48e4b30c4a43fef8bc4b"}, 221 | {file = "pydantic_core-2.10.1-pp38-pypy38_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:154ea7c52e32dce13065dbb20a4a6f0cc012b4f667ac90d648d36b12007fa9f7"}, 222 | {file = "pydantic_core-2.10.1-pp38-pypy38_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:e562617a45b5a9da5be4abe72b971d4f00bf8555eb29bb91ec2ef2be348cd132"}, 223 | {file = "pydantic_core-2.10.1-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:f23b55eb5464468f9e0e9a9935ce3ed2a870608d5f534025cd5536bca25b1402"}, 224 | {file = "pydantic_core-2.10.1-pp39-pypy39_pp73-macosx_10_7_x86_64.whl", hash = "sha256:e9121b4009339b0f751955baf4543a0bfd6bc3f8188f8056b1a25a2d45099934"}, 225 | {file = "pydantic_core-2.10.1-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:0523aeb76e03f753b58be33b26540880bac5aa54422e4462404c432230543f33"}, 226 | {file = "pydantic_core-2.10.1-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2e0e2959ef5d5b8dc9ef21e1a305a21a36e254e6a34432d00c72a92fdc5ecda5"}, 227 | {file = "pydantic_core-2.10.1-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:da01bec0a26befab4898ed83b362993c844b9a607a86add78604186297eb047e"}, 228 | {file = "pydantic_core-2.10.1-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:f2e9072d71c1f6cfc79a36d4484c82823c560e6f5599c43c1ca6b5cdbd54f881"}, 229 | {file = "pydantic_core-2.10.1-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:f36a3489d9e28fe4b67be9992a23029c3cec0babc3bd9afb39f49844a8c721c5"}, 230 | {file = "pydantic_core-2.10.1-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:f64f82cc3443149292b32387086d02a6c7fb39b8781563e0ca7b8d7d9cf72bd7"}, 231 | {file = "pydantic_core-2.10.1-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:b4a6db486ac8e99ae696e09efc8b2b9fea67b63c8f88ba7a1a16c24a057a0776"}, 232 | {file = "pydantic_core-2.10.1.tar.gz", hash = "sha256:0f8682dbdd2f67f8e1edddcbffcc29f60a6182b4901c367fc8c1c40d30bb0a82"}, 233 | ] 234 | 235 | [package.dependencies] 236 | typing-extensions = ">=4.6.0,<4.7.0 || >4.7.0" 237 | 238 | [[package]] 239 | name = "sniffio" 240 | version = "1.3.0" 241 | description = "Sniff out which async library your code is running under" 242 | optional = false 243 | python-versions = ">=3.7" 244 | files = [ 245 | {file = "sniffio-1.3.0-py3-none-any.whl", hash = "sha256:eecefdce1e5bbfb7ad2eeaabf7c1eeb404d7757c379bd1f7e5cce9d8bf425384"}, 246 | {file = "sniffio-1.3.0.tar.gz", hash = "sha256:e60305c5e5d314f5389259b7f22aaa33d8f7dee49763119234af3755c55b9101"}, 247 | ] 248 | 249 | [[package]] 250 | name = "starlette" 251 | version = "0.27.0" 252 | description = "The little ASGI library that shines." 253 | optional = false 254 | python-versions = ">=3.7" 255 | files = [ 256 | {file = "starlette-0.27.0-py3-none-any.whl", hash = "sha256:918416370e846586541235ccd38a474c08b80443ed31c578a418e2209b3eef91"}, 257 | {file = "starlette-0.27.0.tar.gz", hash = "sha256:6a6b0d042acb8d469a01eba54e9cda6cbd24ac602c4cd016723117d6a7e73b75"}, 258 | ] 259 | 260 | [package.dependencies] 261 | anyio = ">=3.4.0,<5" 262 | 263 | [package.extras] 264 | full = ["httpx (>=0.22.0)", "itsdangerous", "jinja2", "python-multipart", "pyyaml"] 265 | 266 | [[package]] 267 | name = "typing-extensions" 268 | version = "4.8.0" 269 | description = "Backported and Experimental Type Hints for Python 3.8+" 270 | optional = false 271 | python-versions = ">=3.8" 272 | files = [ 273 | {file = "typing_extensions-4.8.0-py3-none-any.whl", hash = "sha256:8f92fc8806f9a6b641eaa5318da32b44d401efaac0f6678c9bc448ba3605faa0"}, 274 | {file = "typing_extensions-4.8.0.tar.gz", hash = "sha256:df8e4339e9cb77357558cbdbceca33c303714cf861d1eef15e1070055ae8b7ef"}, 275 | ] 276 | 277 | [[package]] 278 | name = "uvicorn" 279 | version = "0.23.2" 280 | description = "The lightning-fast ASGI server." 281 | optional = false 282 | python-versions = ">=3.8" 283 | files = [ 284 | {file = "uvicorn-0.23.2-py3-none-any.whl", hash = "sha256:1f9be6558f01239d4fdf22ef8126c39cb1ad0addf76c40e760549d2c2f43ab53"}, 285 | {file = "uvicorn-0.23.2.tar.gz", hash = "sha256:4d3cc12d7727ba72b64d12d3cc7743124074c0a69f7b201512fc50c3e3f1569a"}, 286 | ] 287 | 288 | [package.dependencies] 289 | click = ">=7.0" 290 | h11 = ">=0.8" 291 | 292 | [package.extras] 293 | standard = ["colorama (>=0.4)", "httptools (>=0.5.0)", "python-dotenv (>=0.13)", "pyyaml (>=5.1)", "uvloop (>=0.14.0,!=0.15.0,!=0.15.1)", "watchfiles (>=0.13)", "websockets (>=10.4)"] 294 | 295 | [metadata] 296 | lock-version = "2.0" 297 | python-versions = "^3.11" 298 | content-hash = "2d6c104f6cfdf9cd89014e6177ea9833a5135df9fa95641504ec87783b2e02d1" 299 | -------------------------------------------------------------------------------- /backend/pyproject.toml: -------------------------------------------------------------------------------- 1 | [tool.poetry] 2 | name = "nginx-fastapi-vue-docker" 3 | version = "0.1.0" 4 | description = "" 5 | authors = ["Your Name "] 6 | 7 | [[tool.poetry.packages]] 8 | include = "app" 9 | 10 | [tool.poetry.dependencies] 11 | python = "^3.11" 12 | fastapi = "^0.103.2" 13 | 14 | [tool.poetry.group.dev.dependencies] 15 | uvicorn = "^0.23.2" 16 | 17 | [build-system] 18 | requires = ["poetry-core>=1.0.0"] 19 | build-backend = "poetry.core.masonry.api" 20 | -------------------------------------------------------------------------------- /docker/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "access_log": "/dev/stdout", 3 | "listeners": { 4 | "*:80": { 5 | "pass": "routes" 6 | } 7 | }, 8 | "routes": [ 9 | { 10 | "match": { 11 | "uri": "/api/*" 12 | }, 13 | "action": { 14 | "pass": "applications/backend" 15 | } 16 | }, 17 | { 18 | "action": { 19 | "share": "/app/frontend$uri", 20 | "fallback": { 21 | "share": "/app/frontend/index.html" 22 | } 23 | } 24 | } 25 | ], 26 | "applications": { 27 | "backend": { 28 | "type": "python3", 29 | "path": "/app/backend", 30 | "home": "/app/backend/.venv", 31 | "module": "app", 32 | "callable": "app", 33 | "protocol": "asgi" 34 | } 35 | } 36 | } -------------------------------------------------------------------------------- /frontend/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Nginx + Vue + FastAPI + Docker 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /frontend/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "frontend", 3 | "version": "0.1.0", 4 | "private": true, 5 | "type": "module", 6 | "packageManager": "pnpm@8.8.0", 7 | "scripts": { 8 | "dev": "vite", 9 | "build": "vite build", 10 | "preview": "vite preview" 11 | }, 12 | "dependencies": { 13 | "vue": "^3.3.4" 14 | }, 15 | "devDependencies": { 16 | "@vitejs/plugin-vue": "^4.3.4", 17 | "vite": "^4.4.9" 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /frontend/pnpm-lock.yaml: -------------------------------------------------------------------------------- 1 | lockfileVersion: '6.0' 2 | 3 | settings: 4 | autoInstallPeers: true 5 | excludeLinksFromLockfile: false 6 | 7 | dependencies: 8 | vue: 9 | specifier: ^3.3.4 10 | version: 3.3.4 11 | 12 | devDependencies: 13 | '@vitejs/plugin-vue': 14 | specifier: ^4.3.4 15 | version: 4.3.4(vite@4.4.9)(vue@3.3.4) 16 | vite: 17 | specifier: ^4.4.9 18 | version: 4.4.9 19 | 20 | packages: 21 | 22 | /@babel/helper-string-parser@7.22.5: 23 | resolution: {integrity: sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw==} 24 | engines: {node: '>=6.9.0'} 25 | 26 | /@babel/helper-validator-identifier@7.22.20: 27 | resolution: {integrity: sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==} 28 | engines: {node: '>=6.9.0'} 29 | 30 | /@babel/parser@7.23.0: 31 | resolution: {integrity: sha512-vvPKKdMemU85V9WE/l5wZEmImpCtLqbnTvqDS2U1fJ96KrxoW7KrXhNsNCblQlg8Ck4b85yxdTyelsMUgFUXiw==} 32 | engines: {node: '>=6.0.0'} 33 | hasBin: true 34 | dependencies: 35 | '@babel/types': 7.23.0 36 | 37 | /@babel/types@7.23.0: 38 | resolution: {integrity: sha512-0oIyUfKoI3mSqMvsxBdclDwxXKXAUA8v/apZbc+iSyARYou1o8ZGDxbUYyLFoW2arqS2jDGqJuZvv1d/io1axg==} 39 | engines: {node: '>=6.9.0'} 40 | dependencies: 41 | '@babel/helper-string-parser': 7.22.5 42 | '@babel/helper-validator-identifier': 7.22.20 43 | to-fast-properties: 2.0.0 44 | 45 | /@esbuild/android-arm64@0.18.20: 46 | resolution: {integrity: sha512-Nz4rJcchGDtENV0eMKUNa6L12zz2zBDXuhj/Vjh18zGqB44Bi7MBMSXjgunJgjRhCmKOjnPuZp4Mb6OKqtMHLQ==} 47 | engines: {node: '>=12'} 48 | cpu: [arm64] 49 | os: [android] 50 | requiresBuild: true 51 | dev: true 52 | optional: true 53 | 54 | /@esbuild/android-arm@0.18.20: 55 | resolution: {integrity: sha512-fyi7TDI/ijKKNZTUJAQqiG5T7YjJXgnzkURqmGj13C6dCqckZBLdl4h7bkhHt/t0WP+zO9/zwroDvANaOqO5Sw==} 56 | engines: {node: '>=12'} 57 | cpu: [arm] 58 | os: [android] 59 | requiresBuild: true 60 | dev: true 61 | optional: true 62 | 63 | /@esbuild/android-x64@0.18.20: 64 | resolution: {integrity: sha512-8GDdlePJA8D6zlZYJV/jnrRAi6rOiNaCC/JclcXpB+KIuvfBN4owLtgzY2bsxnx666XjJx2kDPUmnTtR8qKQUg==} 65 | engines: {node: '>=12'} 66 | cpu: [x64] 67 | os: [android] 68 | requiresBuild: true 69 | dev: true 70 | optional: true 71 | 72 | /@esbuild/darwin-arm64@0.18.20: 73 | resolution: {integrity: sha512-bxRHW5kHU38zS2lPTPOyuyTm+S+eobPUnTNkdJEfAddYgEcll4xkT8DB9d2008DtTbl7uJag2HuE5NZAZgnNEA==} 74 | engines: {node: '>=12'} 75 | cpu: [arm64] 76 | os: [darwin] 77 | requiresBuild: true 78 | dev: true 79 | optional: true 80 | 81 | /@esbuild/darwin-x64@0.18.20: 82 | resolution: {integrity: sha512-pc5gxlMDxzm513qPGbCbDukOdsGtKhfxD1zJKXjCCcU7ju50O7MeAZ8c4krSJcOIJGFR+qx21yMMVYwiQvyTyQ==} 83 | engines: {node: '>=12'} 84 | cpu: [x64] 85 | os: [darwin] 86 | requiresBuild: true 87 | dev: true 88 | optional: true 89 | 90 | /@esbuild/freebsd-arm64@0.18.20: 91 | resolution: {integrity: sha512-yqDQHy4QHevpMAaxhhIwYPMv1NECwOvIpGCZkECn8w2WFHXjEwrBn3CeNIYsibZ/iZEUemj++M26W3cNR5h+Tw==} 92 | engines: {node: '>=12'} 93 | cpu: [arm64] 94 | os: [freebsd] 95 | requiresBuild: true 96 | dev: true 97 | optional: true 98 | 99 | /@esbuild/freebsd-x64@0.18.20: 100 | resolution: {integrity: sha512-tgWRPPuQsd3RmBZwarGVHZQvtzfEBOreNuxEMKFcd5DaDn2PbBxfwLcj4+aenoh7ctXcbXmOQIn8HI6mCSw5MQ==} 101 | engines: {node: '>=12'} 102 | cpu: [x64] 103 | os: [freebsd] 104 | requiresBuild: true 105 | dev: true 106 | optional: true 107 | 108 | /@esbuild/linux-arm64@0.18.20: 109 | resolution: {integrity: sha512-2YbscF+UL7SQAVIpnWvYwM+3LskyDmPhe31pE7/aoTMFKKzIc9lLbyGUpmmb8a8AixOL61sQ/mFh3jEjHYFvdA==} 110 | engines: {node: '>=12'} 111 | cpu: [arm64] 112 | os: [linux] 113 | requiresBuild: true 114 | dev: true 115 | optional: true 116 | 117 | /@esbuild/linux-arm@0.18.20: 118 | resolution: {integrity: sha512-/5bHkMWnq1EgKr1V+Ybz3s1hWXok7mDFUMQ4cG10AfW3wL02PSZi5kFpYKrptDsgb2WAJIvRcDm+qIvXf/apvg==} 119 | engines: {node: '>=12'} 120 | cpu: [arm] 121 | os: [linux] 122 | requiresBuild: true 123 | dev: true 124 | optional: true 125 | 126 | /@esbuild/linux-ia32@0.18.20: 127 | resolution: {integrity: sha512-P4etWwq6IsReT0E1KHU40bOnzMHoH73aXp96Fs8TIT6z9Hu8G6+0SHSw9i2isWrD2nbx2qo5yUqACgdfVGx7TA==} 128 | engines: {node: '>=12'} 129 | cpu: [ia32] 130 | os: [linux] 131 | requiresBuild: true 132 | dev: true 133 | optional: true 134 | 135 | /@esbuild/linux-loong64@0.18.20: 136 | resolution: {integrity: sha512-nXW8nqBTrOpDLPgPY9uV+/1DjxoQ7DoB2N8eocyq8I9XuqJ7BiAMDMf9n1xZM9TgW0J8zrquIb/A7s3BJv7rjg==} 137 | engines: {node: '>=12'} 138 | cpu: [loong64] 139 | os: [linux] 140 | requiresBuild: true 141 | dev: true 142 | optional: true 143 | 144 | /@esbuild/linux-mips64el@0.18.20: 145 | resolution: {integrity: sha512-d5NeaXZcHp8PzYy5VnXV3VSd2D328Zb+9dEq5HE6bw6+N86JVPExrA6O68OPwobntbNJ0pzCpUFZTo3w0GyetQ==} 146 | engines: {node: '>=12'} 147 | cpu: [mips64el] 148 | os: [linux] 149 | requiresBuild: true 150 | dev: true 151 | optional: true 152 | 153 | /@esbuild/linux-ppc64@0.18.20: 154 | resolution: {integrity: sha512-WHPyeScRNcmANnLQkq6AfyXRFr5D6N2sKgkFo2FqguP44Nw2eyDlbTdZwd9GYk98DZG9QItIiTlFLHJHjxP3FA==} 155 | engines: {node: '>=12'} 156 | cpu: [ppc64] 157 | os: [linux] 158 | requiresBuild: true 159 | dev: true 160 | optional: true 161 | 162 | /@esbuild/linux-riscv64@0.18.20: 163 | resolution: {integrity: sha512-WSxo6h5ecI5XH34KC7w5veNnKkju3zBRLEQNY7mv5mtBmrP/MjNBCAlsM2u5hDBlS3NGcTQpoBvRzqBcRtpq1A==} 164 | engines: {node: '>=12'} 165 | cpu: [riscv64] 166 | os: [linux] 167 | requiresBuild: true 168 | dev: true 169 | optional: true 170 | 171 | /@esbuild/linux-s390x@0.18.20: 172 | resolution: {integrity: sha512-+8231GMs3mAEth6Ja1iK0a1sQ3ohfcpzpRLH8uuc5/KVDFneH6jtAJLFGafpzpMRO6DzJ6AvXKze9LfFMrIHVQ==} 173 | engines: {node: '>=12'} 174 | cpu: [s390x] 175 | os: [linux] 176 | requiresBuild: true 177 | dev: true 178 | optional: true 179 | 180 | /@esbuild/linux-x64@0.18.20: 181 | resolution: {integrity: sha512-UYqiqemphJcNsFEskc73jQ7B9jgwjWrSayxawS6UVFZGWrAAtkzjxSqnoclCXxWtfwLdzU+vTpcNYhpn43uP1w==} 182 | engines: {node: '>=12'} 183 | cpu: [x64] 184 | os: [linux] 185 | requiresBuild: true 186 | dev: true 187 | optional: true 188 | 189 | /@esbuild/netbsd-x64@0.18.20: 190 | resolution: {integrity: sha512-iO1c++VP6xUBUmltHZoMtCUdPlnPGdBom6IrO4gyKPFFVBKioIImVooR5I83nTew5UOYrk3gIJhbZh8X44y06A==} 191 | engines: {node: '>=12'} 192 | cpu: [x64] 193 | os: [netbsd] 194 | requiresBuild: true 195 | dev: true 196 | optional: true 197 | 198 | /@esbuild/openbsd-x64@0.18.20: 199 | resolution: {integrity: sha512-e5e4YSsuQfX4cxcygw/UCPIEP6wbIL+se3sxPdCiMbFLBWu0eiZOJ7WoD+ptCLrmjZBK1Wk7I6D/I3NglUGOxg==} 200 | engines: {node: '>=12'} 201 | cpu: [x64] 202 | os: [openbsd] 203 | requiresBuild: true 204 | dev: true 205 | optional: true 206 | 207 | /@esbuild/sunos-x64@0.18.20: 208 | resolution: {integrity: sha512-kDbFRFp0YpTQVVrqUd5FTYmWo45zGaXe0X8E1G/LKFC0v8x0vWrhOWSLITcCn63lmZIxfOMXtCfti/RxN/0wnQ==} 209 | engines: {node: '>=12'} 210 | cpu: [x64] 211 | os: [sunos] 212 | requiresBuild: true 213 | dev: true 214 | optional: true 215 | 216 | /@esbuild/win32-arm64@0.18.20: 217 | resolution: {integrity: sha512-ddYFR6ItYgoaq4v4JmQQaAI5s7npztfV4Ag6NrhiaW0RrnOXqBkgwZLofVTlq1daVTQNhtI5oieTvkRPfZrePg==} 218 | engines: {node: '>=12'} 219 | cpu: [arm64] 220 | os: [win32] 221 | requiresBuild: true 222 | dev: true 223 | optional: true 224 | 225 | /@esbuild/win32-ia32@0.18.20: 226 | resolution: {integrity: sha512-Wv7QBi3ID/rROT08SABTS7eV4hX26sVduqDOTe1MvGMjNd3EjOz4b7zeexIR62GTIEKrfJXKL9LFxTYgkyeu7g==} 227 | engines: {node: '>=12'} 228 | cpu: [ia32] 229 | os: [win32] 230 | requiresBuild: true 231 | dev: true 232 | optional: true 233 | 234 | /@esbuild/win32-x64@0.18.20: 235 | resolution: {integrity: sha512-kTdfRcSiDfQca/y9QIkng02avJ+NCaQvrMejlsB3RRv5sE9rRoeBPISaZpKxHELzRxZyLvNts1P27W3wV+8geQ==} 236 | engines: {node: '>=12'} 237 | cpu: [x64] 238 | os: [win32] 239 | requiresBuild: true 240 | dev: true 241 | optional: true 242 | 243 | /@jridgewell/sourcemap-codec@1.4.15: 244 | resolution: {integrity: sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==} 245 | 246 | /@vitejs/plugin-vue@4.3.4(vite@4.4.9)(vue@3.3.4): 247 | resolution: {integrity: sha512-ciXNIHKPriERBisHFBvnTbfKa6r9SAesOYXeGDzgegcvy9Q4xdScSHAmKbNT0M3O0S9LKhIf5/G+UYG4NnnzYw==} 248 | engines: {node: ^14.18.0 || >=16.0.0} 249 | peerDependencies: 250 | vite: ^4.0.0 251 | vue: ^3.2.25 252 | dependencies: 253 | vite: 4.4.9 254 | vue: 3.3.4 255 | dev: true 256 | 257 | /@vue/compiler-core@3.3.4: 258 | resolution: {integrity: sha512-cquyDNvZ6jTbf/+x+AgM2Arrp6G4Dzbb0R64jiG804HRMfRiFXWI6kqUVqZ6ZR0bQhIoQjB4+2bhNtVwndW15g==} 259 | dependencies: 260 | '@babel/parser': 7.23.0 261 | '@vue/shared': 3.3.4 262 | estree-walker: 2.0.2 263 | source-map-js: 1.0.2 264 | 265 | /@vue/compiler-dom@3.3.4: 266 | resolution: {integrity: sha512-wyM+OjOVpuUukIq6p5+nwHYtj9cFroz9cwkfmP9O1nzH68BenTTv0u7/ndggT8cIQlnBeOo6sUT/gvHcIkLA5w==} 267 | dependencies: 268 | '@vue/compiler-core': 3.3.4 269 | '@vue/shared': 3.3.4 270 | 271 | /@vue/compiler-sfc@3.3.4: 272 | resolution: {integrity: sha512-6y/d8uw+5TkCuzBkgLS0v3lSM3hJDntFEiUORM11pQ/hKvkhSKZrXW6i69UyXlJQisJxuUEJKAWEqWbWsLeNKQ==} 273 | dependencies: 274 | '@babel/parser': 7.23.0 275 | '@vue/compiler-core': 3.3.4 276 | '@vue/compiler-dom': 3.3.4 277 | '@vue/compiler-ssr': 3.3.4 278 | '@vue/reactivity-transform': 3.3.4 279 | '@vue/shared': 3.3.4 280 | estree-walker: 2.0.2 281 | magic-string: 0.30.4 282 | postcss: 8.4.31 283 | source-map-js: 1.0.2 284 | 285 | /@vue/compiler-ssr@3.3.4: 286 | resolution: {integrity: sha512-m0v6oKpup2nMSehwA6Uuu+j+wEwcy7QmwMkVNVfrV9P2qE5KshC6RwOCq8fjGS/Eak/uNb8AaWekfiXxbBB6gQ==} 287 | dependencies: 288 | '@vue/compiler-dom': 3.3.4 289 | '@vue/shared': 3.3.4 290 | 291 | /@vue/reactivity-transform@3.3.4: 292 | resolution: {integrity: sha512-MXgwjako4nu5WFLAjpBnCj/ieqcjE2aJBINUNQzkZQfzIZA4xn+0fV1tIYBJvvva3N3OvKGofRLvQIwEQPpaXw==} 293 | dependencies: 294 | '@babel/parser': 7.23.0 295 | '@vue/compiler-core': 3.3.4 296 | '@vue/shared': 3.3.4 297 | estree-walker: 2.0.2 298 | magic-string: 0.30.4 299 | 300 | /@vue/reactivity@3.3.4: 301 | resolution: {integrity: sha512-kLTDLwd0B1jG08NBF3R5rqULtv/f8x3rOFByTDz4J53ttIQEDmALqKqXY0J+XQeN0aV2FBxY8nJDf88yvOPAqQ==} 302 | dependencies: 303 | '@vue/shared': 3.3.4 304 | 305 | /@vue/runtime-core@3.3.4: 306 | resolution: {integrity: sha512-R+bqxMN6pWO7zGI4OMlmvePOdP2c93GsHFM/siJI7O2nxFRzj55pLwkpCedEY+bTMgp5miZ8CxfIZo3S+gFqvA==} 307 | dependencies: 308 | '@vue/reactivity': 3.3.4 309 | '@vue/shared': 3.3.4 310 | 311 | /@vue/runtime-dom@3.3.4: 312 | resolution: {integrity: sha512-Aj5bTJ3u5sFsUckRghsNjVTtxZQ1OyMWCr5dZRAPijF/0Vy4xEoRCwLyHXcj4D0UFbJ4lbx3gPTgg06K/GnPnQ==} 313 | dependencies: 314 | '@vue/runtime-core': 3.3.4 315 | '@vue/shared': 3.3.4 316 | csstype: 3.1.2 317 | 318 | /@vue/server-renderer@3.3.4(vue@3.3.4): 319 | resolution: {integrity: sha512-Q6jDDzR23ViIb67v+vM1Dqntu+HUexQcsWKhhQa4ARVzxOY2HbC7QRW/ggkDBd5BU+uM1sV6XOAP0b216o34JQ==} 320 | peerDependencies: 321 | vue: 3.3.4 322 | dependencies: 323 | '@vue/compiler-ssr': 3.3.4 324 | '@vue/shared': 3.3.4 325 | vue: 3.3.4 326 | 327 | /@vue/shared@3.3.4: 328 | resolution: {integrity: sha512-7OjdcV8vQ74eiz1TZLzZP4JwqM5fA94K6yntPS5Z25r9HDuGNzaGdgvwKYq6S+MxwF0TFRwe50fIR/MYnakdkQ==} 329 | 330 | /csstype@3.1.2: 331 | resolution: {integrity: sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ==} 332 | 333 | /esbuild@0.18.20: 334 | resolution: {integrity: sha512-ceqxoedUrcayh7Y7ZX6NdbbDzGROiyVBgC4PriJThBKSVPWnnFHZAkfI1lJT8QFkOwH4qOS2SJkS4wvpGl8BpA==} 335 | engines: {node: '>=12'} 336 | hasBin: true 337 | requiresBuild: true 338 | optionalDependencies: 339 | '@esbuild/android-arm': 0.18.20 340 | '@esbuild/android-arm64': 0.18.20 341 | '@esbuild/android-x64': 0.18.20 342 | '@esbuild/darwin-arm64': 0.18.20 343 | '@esbuild/darwin-x64': 0.18.20 344 | '@esbuild/freebsd-arm64': 0.18.20 345 | '@esbuild/freebsd-x64': 0.18.20 346 | '@esbuild/linux-arm': 0.18.20 347 | '@esbuild/linux-arm64': 0.18.20 348 | '@esbuild/linux-ia32': 0.18.20 349 | '@esbuild/linux-loong64': 0.18.20 350 | '@esbuild/linux-mips64el': 0.18.20 351 | '@esbuild/linux-ppc64': 0.18.20 352 | '@esbuild/linux-riscv64': 0.18.20 353 | '@esbuild/linux-s390x': 0.18.20 354 | '@esbuild/linux-x64': 0.18.20 355 | '@esbuild/netbsd-x64': 0.18.20 356 | '@esbuild/openbsd-x64': 0.18.20 357 | '@esbuild/sunos-x64': 0.18.20 358 | '@esbuild/win32-arm64': 0.18.20 359 | '@esbuild/win32-ia32': 0.18.20 360 | '@esbuild/win32-x64': 0.18.20 361 | dev: true 362 | 363 | /estree-walker@2.0.2: 364 | resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==} 365 | 366 | /fsevents@2.3.3: 367 | resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} 368 | engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} 369 | os: [darwin] 370 | requiresBuild: true 371 | dev: true 372 | optional: true 373 | 374 | /magic-string@0.30.4: 375 | resolution: {integrity: sha512-Q/TKtsC5BPm0kGqgBIF9oXAs/xEf2vRKiIB4wCRQTJOQIByZ1d+NnUOotvJOvNpi5RNIgVOMC3pOuaP1ZTDlVg==} 376 | engines: {node: '>=12'} 377 | dependencies: 378 | '@jridgewell/sourcemap-codec': 1.4.15 379 | 380 | /nanoid@3.3.6: 381 | resolution: {integrity: sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==} 382 | engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} 383 | hasBin: true 384 | 385 | /picocolors@1.0.0: 386 | resolution: {integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==} 387 | 388 | /postcss@8.4.31: 389 | resolution: {integrity: sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==} 390 | engines: {node: ^10 || ^12 || >=14} 391 | dependencies: 392 | nanoid: 3.3.6 393 | picocolors: 1.0.0 394 | source-map-js: 1.0.2 395 | 396 | /rollup@3.29.4: 397 | resolution: {integrity: sha512-oWzmBZwvYrU0iJHtDmhsm662rC15FRXmcjCk1xD771dFDx5jJ02ufAQQTn0etB2emNk4J9EZg/yWKpsn9BWGRw==} 398 | engines: {node: '>=14.18.0', npm: '>=8.0.0'} 399 | hasBin: true 400 | optionalDependencies: 401 | fsevents: 2.3.3 402 | dev: true 403 | 404 | /source-map-js@1.0.2: 405 | resolution: {integrity: sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==} 406 | engines: {node: '>=0.10.0'} 407 | 408 | /to-fast-properties@2.0.0: 409 | resolution: {integrity: sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==} 410 | engines: {node: '>=4'} 411 | 412 | /vite@4.4.9: 413 | resolution: {integrity: sha512-2mbUn2LlUmNASWwSCNSJ/EG2HuSRTnVNaydp6vMCm5VIqJsjMfbIWtbH2kDuwUVW5mMUKKZvGPX/rqeqVvv1XA==} 414 | engines: {node: ^14.18.0 || >=16.0.0} 415 | hasBin: true 416 | peerDependencies: 417 | '@types/node': '>= 14' 418 | less: '*' 419 | lightningcss: ^1.21.0 420 | sass: '*' 421 | stylus: '*' 422 | sugarss: '*' 423 | terser: ^5.4.0 424 | peerDependenciesMeta: 425 | '@types/node': 426 | optional: true 427 | less: 428 | optional: true 429 | lightningcss: 430 | optional: true 431 | sass: 432 | optional: true 433 | stylus: 434 | optional: true 435 | sugarss: 436 | optional: true 437 | terser: 438 | optional: true 439 | dependencies: 440 | esbuild: 0.18.20 441 | postcss: 8.4.31 442 | rollup: 3.29.4 443 | optionalDependencies: 444 | fsevents: 2.3.3 445 | dev: true 446 | 447 | /vue@3.3.4: 448 | resolution: {integrity: sha512-VTyEYn3yvIeY1Py0WaYGZsXnz3y5UnGi62GjVEqvEGPl6nxbOrCXbVOTQWBEJUqAyTUk2uJ5JLVnYJ6ZzGbrSw==} 449 | dependencies: 450 | '@vue/compiler-dom': 3.3.4 451 | '@vue/compiler-sfc': 3.3.4 452 | '@vue/runtime-dom': 3.3.4 453 | '@vue/server-renderer': 3.3.4(vue@3.3.4) 454 | '@vue/shared': 3.3.4 455 | -------------------------------------------------------------------------------- /frontend/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mattmess1221/nginx-fastapi-vue-docker/239bcc7e29be6d18731a17350c992b93fe4517c1/frontend/public/favicon.ico -------------------------------------------------------------------------------- /frontend/src/App.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 39 | 40 | 50 | -------------------------------------------------------------------------------- /frontend/src/main.js: -------------------------------------------------------------------------------- 1 | import { createApp } from 'vue' 2 | import App from './App.vue' 3 | 4 | createApp(App).mount('#app') 5 | -------------------------------------------------------------------------------- /frontend/vite.config.js: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'vite' 2 | import vue from '@vitejs/plugin-vue' 3 | 4 | export default defineConfig({ 5 | plugins: [vue()], 6 | server: { 7 | proxy: { 8 | '^/api/': { 9 | target: 'http://localhost:8000/' 10 | } 11 | } 12 | } 13 | }) 14 | --------------------------------------------------------------------------------