mirror of
https://github.com/docker/awesome-compose.git
synced 2025-04-19 15:28:06 +02:00
Merge branch 'docker:master' into feature/testcontainers
This commit is contained in:
commit
1ef170e10a
64 changed files with 1011 additions and 845 deletions
52
README.md
52
README.md
|
@ -18,54 +18,54 @@ These samples provide a starting point for how to integrate different services u
|
|||
|
||||
## Samples of Docker Compose applications with multiple integrated services
|
||||
|
||||
<a href="https://docs.docker.com/desktop/dev-environments/"><img src="icon_devenvs.svg" alt="Use with Docker Dev Environments" height="30" align="top"/></a> Icon indicates Sample is compatible with [Docker Dev Environments](https://docs.docker.com/desktop/dev-environments/) in Docker Desktop version 4.10 or later.
|
||||
<a href="https://docs.docker.com/desktop/wasm/"><img src="icon_wasm.svg" alt="Docker + wasm" height="30" align="top"/></a> Icon indicates Sample is compatible with [Docker+Wasm](https://docs.docker.com/desktop/wasm/).
|
||||
|
||||
- [`ASP.NET / MS-SQL`](aspnet-mssql) - Sample ASP.NET core application
|
||||
with MS SQL server database.
|
||||
- [`Elasticsearch / Logstash / Kibana`](elasticsearch-logstash-kibana) - Sample Elasticsearch, Logstash, and Kibana stack.
|
||||
- [`Go / NGINX / MySQL`](nginx-golang-mysql) - Sample Go application
|
||||
with an Nginx proxy and a MySQL database. <a href="nginx-golang-mysql"><img src="icon_devenvs.svg" alt="Use with Docker Dev Environments" height="30" align="top"/></a>
|
||||
with an Nginx proxy and a MySQL database.
|
||||
- [`Go / NGINX / PostgreSQL`](nginx-golang-postgres) - Sample Go
|
||||
application with an Nginx proxy and a PostgreSQL database. <a href="nginx-golang-postgres"><img src="icon_devenvs.svg" alt="Use with Docker Dev Environments" height="30" align="top"/></a>
|
||||
application with an Nginx proxy and a PostgreSQL database.
|
||||
- [`Java Spark / MySQL`](sparkjava-mysql) - Sample Java application and
|
||||
a MySQL database. <a href="sparkjava-mysql"><img src="icon_devenvs.svg" alt="Use with Docker Dev Environments" height="30" align="top"/></a>
|
||||
- [`NGINX / ASP.NET / MySQL`](nginx-aspnet-mysql) - Sample Nginx reverse proxy with an C# backend using ASP.NET <a href="nginx-aspnet-mysql"><img src="icon_devenvs.svg" alt="Use with Docker Dev Environments" height="30" align="top"/></a>
|
||||
a MySQL database.
|
||||
- [`NGINX / ASP.NET / MySQL`](nginx-aspnet-mysql) - Sample Nginx reverse proxy with an C# backend using ASP.NET.
|
||||
- [`NGINX / Flask / MongoDB`](nginx-flask-mongo) - Sample Python/Flask
|
||||
application with Nginx proxy and a Mongo database. <a href="nginx-flask-mongo"><img src="icon_devenvs.svg" alt="Use with Docker Dev Environments" height="30" align="top"/></a>
|
||||
application with Nginx proxy and a Mongo database.
|
||||
- [`NGINX / Flask / MySQL`](nginx-flask-mysql) - Sample Python/Flask application with an Nginx proxy and a MySQL database.
|
||||
- [`NGINX / Node.js / Redis`](nginx-nodejs-redis) - Sample Node.js application with Nginx proxy and a Redis database
|
||||
- [`NGINX / Go`](nginx-golang) - Sample Nginx proxy with a Go backend. <a href="nginx-golang"><img src="icon_devenvs.svg" alt="Use with Docker Dev Environments" height="30" align="top"/></a>
|
||||
- [`NGINX / Node.js / Redis`](nginx-nodejs-redis) - Sample Node.js application with Nginx proxy and a Redis database.
|
||||
- [`NGINX / Go`](nginx-golang) - Sample Nginx proxy with a Go backend.
|
||||
- [`NGINX / WSGI / Flask`](nginx-wsgi-flask) - Sample Nginx reverse proxy with a Flask backend using WSGI.
|
||||
- [`PostgreSQL / pgAdmin`](postgresql-pgadmin) - Sample setup for postgreSQL database with pgAdmin web interface
|
||||
- [`Python / Flask / Redis`](flask-redis) - Sample Python/Flask and a Redis database <a href="flask-redis"><img src="icon_devenvs.svg" alt="Use with Docker Dev Environments" height="30" align="top"/></a>
|
||||
- [`PostgreSQL / pgAdmin`](postgresql-pgadmin) - Sample setup for postgreSQL database with pgAdmin web interface.
|
||||
- [`Python / Flask / Redis`](flask-redis) - Sample Python/Flask and a Redis database.
|
||||
- [`React / Spring / MySQL`](react-java-mysql) - Sample React
|
||||
application with a Spring backend and a MySQL database. <a href="react-java-mysql"><img src="icon_devenvs.svg" alt="Use with Docker Dev Environments" height="30" align="top"/></a>
|
||||
application with a Spring backend and a MySQL database.
|
||||
- [`React / Express / MySQL`](react-express-mysql) - Sample React
|
||||
application with a Node.js backend and a MySQL database. <a href="react-express-mysql"><img src="icon_devenvs.svg" alt="Use with Docker Dev Environments" height="30" align="top"/></a>
|
||||
application with a Node.js backend and a MySQL database.
|
||||
- [`React / Express / MongoDB`](react-express-mongodb) - Sample React
|
||||
application with a Node.js backend and a Mongo database. <a href="react-express-mongodb"><img src="icon_devenvs.svg" alt="Use with Docker Dev Environments" height="30" align="top"/></a>
|
||||
application with a Node.js backend and a Mongo database.
|
||||
- [`React / Rust / PostgreSQL`](react-rust-postgres) - Sample React
|
||||
application with a Rust backend and a Postgres database. <a href="react-rust-postgres"><img src="icon_devenvs.svg" alt="Use with Docker Dev Environments" height="30" align="top"/></a>
|
||||
- [`React / Nginx`](react-nginx) - Sample React application with Nginx. <a href="react-nginx"><img src="icon_devenvs.svg" alt="Use with Docker Dev Environments" height="30" align="top"/></a>
|
||||
application with a Rust backend and a Postgres database.
|
||||
- [`React / Nginx`](react-nginx) - Sample React application with Nginx.
|
||||
- [`Spring / PostgreSQL`](spring-postgres) - Sample Java application
|
||||
with Spring framework and a Postgres database. <a href="spring-postgres"><img src="icon_devenvs.svg" alt="Use with Docker Dev Environments" height="30" align="top"/></a>
|
||||
with Spring framework and a Postgres database.
|
||||
- [`WasmEdge / MySQL / Nginx`](wasmedge-mysql-nginx) - Sample Wasm-based web application with a static HTML frontend, using a MySQL (MariaDB) database. The frontend connects to a Wasm microservice written in Rust, that runs using the WasmEdge runtime. <a href="wasmedge-mysql-nginx"><img src="icon_wasm.svg" alt="Compatible with Docker+wasm" height="30" align="top"/></a>
|
||||
- [`WasmEdge / Kafka / MySQL`](wasmedge-kafka-mysql) - Sample Wasm-based microservice that subscribes to a Kafka (Redpanda) queue topic, and transforms and saves any incoming message into a MySQL (MariaDB) database. <a href="wasmedge-kafka-mysql"><img src="icon_wasm.svg" alt="Compatible with Docker+wasm" height="30" align="top"/></a>
|
||||
|
||||
## Single service samples
|
||||
|
||||
<a href="https://docs.docker.com/desktop/dev-environments/"><img src="icon_devenvs.svg" alt="Use with Docker Dev Environments" height="30" align="top"/></a> Icon indicates Sample is compatible with [Docker Dev Environments](https://docs.docker.com/desktop/dev-environments/) in Docker Desktop version 4.10 or later.
|
||||
|
||||
- [`Angular`](angular) <a href="angular"><img src="icon_devenvs.svg" alt="Use with Docker Dev Environments" height="30" align="top"/></a>
|
||||
- [`Spark`](sparkjava) <a href="sparkjava"><img src="icon_devenvs.svg" alt="Use with Docker Dev Environments" height="30" align="top"/></a>
|
||||
- [`VueJS`](vuejs) <a href="vuejs"><img src="icon_devenvs.svg" alt="Use with Docker Dev Environments" height="30" align="top"/></a>
|
||||
- [`Flask`](flask) <a href="flask"><img src="icon_devenvs.svg" alt="Use with Docker Dev Environments" height="30" align="top"/></a>
|
||||
- [`PHP`](apache-php) <a href="apache-php"><img src="icon_devenvs.svg" alt="Use with Docker Dev Environments" height="30" align="top"/></a>
|
||||
- [`Traefik`](traefik-golang) <a href="traefik-golang"><img src="icon_devenvs.svg" alt="Use with Docker Dev Environments" height="30" align="top"/></a>
|
||||
- [`Django`](django) <a href="django"><img src="icon_devenvs.svg" alt="Use with Docker Dev Environments" height="30" align="top"/></a>
|
||||
- [`Angular`](angular)
|
||||
- [`Spark`](sparkjava)
|
||||
- [`VueJS`](vuejs)
|
||||
- [`Flask`](flask)
|
||||
- [`PHP`](apache-php)
|
||||
- [`Traefik`](traefik-golang)
|
||||
- [`Django`](django)
|
||||
- [`Minecraft server`](https://github.com/docker/awesome-compose/tree/master/minecraft)
|
||||
- [`Plex`](https://github.com/docker/awesome-compose/tree/master/plex)
|
||||
- [`Portainer`](https://github.com/docker/awesome-compose/tree/master/portainer)
|
||||
- [`Wireguard`](https://github.com/docker/awesome-compose/tree/master/wireguard)
|
||||
- [`FastAPI`](fastapi) <a href="fastapi#use-with-docker-development-environments"><img src="icon_devenvs.svg" alt="Use with Docker Dev Environments" height="30" align="top"/></a>
|
||||
- [`FastAPI`](fastapi)
|
||||
|
||||
## Basic setups for different platforms (not production ready - useful for personal use)
|
||||
|
||||
|
|
|
@ -1,11 +0,0 @@
|
|||
services:
|
||||
web:
|
||||
build:
|
||||
context: angular
|
||||
target: dev-envs
|
||||
ports:
|
||||
- 4200:4200
|
||||
volumes:
|
||||
- /var/run/docker.sock:/var/run/docker.sock
|
||||
- ./angular:/project
|
||||
- /project/node_modules
|
|
@ -1,11 +1,4 @@
|
|||
## Compose sample
|
||||
|
||||
### Use with Docker Development Environments
|
||||
|
||||
You can open this sample in the Dev Environments feature of Docker Desktop version 4.12 or later.
|
||||
|
||||
[Open in Docker Dev Environments <img src="../open_in_new.svg" alt="Open in Docker Dev Environments" align="top"/>](https://open.docker.com/dashboard/dev-envs?url=https://github.com/docker/awesome-compose/tree/master/angular)
|
||||
|
||||
### Angular service
|
||||
|
||||
Project structure:
|
||||
|
|
|
@ -1,10 +0,0 @@
|
|||
services:
|
||||
web:
|
||||
build:
|
||||
context: app
|
||||
target: dev-envs
|
||||
ports:
|
||||
- '80:80'
|
||||
volumes:
|
||||
- /var/run/docker.sock:/var/run/docker.sock
|
||||
- ./app:/var/www/html/
|
|
@ -1,11 +1,4 @@
|
|||
## Compose sample application
|
||||
|
||||
### Use with Docker Development Environments
|
||||
|
||||
You can open this sample in the Dev Environments feature of Docker Desktop version 4.12 or later.
|
||||
|
||||
[Open in Docker Dev Environments <img src="../open_in_new.svg" alt="Open in Docker Dev Environments" align="top"/>](https://open.docker.com/dashboard/dev-envs?url=https://github.com/docker/awesome-compose/tree/master/apache-php)
|
||||
|
||||
### PHP application with Apache2
|
||||
|
||||
Project structure:
|
||||
|
|
|
@ -1,9 +0,0 @@
|
|||
services:
|
||||
web:
|
||||
build:
|
||||
context: app
|
||||
target: dev-envs
|
||||
ports:
|
||||
- '8000:8000'
|
||||
volumes:
|
||||
- /var/run/docker.sock:/var/run/docker.sock
|
|
@ -1,11 +1,4 @@
|
|||
## Compose sample application
|
||||
|
||||
### Use with Docker Development Environments
|
||||
|
||||
You can open this sample in the Dev Environments feature of Docker Desktop version 4.12 or later.
|
||||
|
||||
[Open in Docker Dev Environments <img src="../open_in_new.svg" alt="Open in Docker Dev Environments" align="top"/>](https://open.docker.com/dashboard/dev-envs?url=https://github.com/docker/awesome-compose/tree/master/django)
|
||||
|
||||
### Django application in dev mode
|
||||
|
||||
Project structure:
|
||||
|
|
|
@ -1,13 +0,0 @@
|
|||
services:
|
||||
api:
|
||||
build:
|
||||
context: .
|
||||
target: dev-envs
|
||||
container_name: fastapi-application
|
||||
environment:
|
||||
PORT: 8000
|
||||
ports:
|
||||
- '8000:8000'
|
||||
volumes:
|
||||
- /var/run/docker.sock:/var/run/docker.sock
|
||||
restart: "no"
|
|
@ -1,11 +1,4 @@
|
|||
## Compose sample application
|
||||
|
||||
### Use with Docker Development Environments
|
||||
|
||||
You can open this sample in the Dev Environments feature of Docker Desktop version 4.12 or later.
|
||||
|
||||
[Open in Docker Dev Environments <img src="../open_in_new.svg" alt="Open in Docker Dev Environments" align="top"/>](https://open.docker.com/dashboard/dev-envs?url=https://github.com/docker/awesome-compose/tree/master/fastapi)
|
||||
|
||||
### Python/FastAPI application
|
||||
|
||||
Project structure:
|
||||
|
|
|
@ -1,16 +0,0 @@
|
|||
services:
|
||||
redis:
|
||||
image: redislabs/redismod
|
||||
ports:
|
||||
- '6379:6379'
|
||||
web:
|
||||
build:
|
||||
context: .
|
||||
target: dev-envs
|
||||
stop_signal: SIGINT
|
||||
ports:
|
||||
- '8000:8000'
|
||||
volumes:
|
||||
- /var/run/docker.sock:/var/run/docker.sock
|
||||
depends_on:
|
||||
- redis
|
|
@ -1,11 +1,4 @@
|
|||
## Compose sample application
|
||||
|
||||
### Use with Docker Development Environments
|
||||
|
||||
You can open this sample in the Dev Environments feature of Docker Desktop version 4.12 or later.
|
||||
|
||||
[Open in Docker Dev Environments <img src="../open_in_new.svg" alt="Open in Docker Dev Environments" align="top"/>](https://open.docker.com/dashboard/dev-envs?url=https://github.com/docker/awesome-compose/tree/master/flask-redis)
|
||||
|
||||
### Python/Flask application using a Redis database
|
||||
|
||||
Project structure:
|
||||
|
|
|
@ -1,10 +0,0 @@
|
|||
services:
|
||||
web:
|
||||
build:
|
||||
context: app
|
||||
target: dev-envs
|
||||
stop_signal: SIGINT
|
||||
ports:
|
||||
- '8000:8000'
|
||||
volumes:
|
||||
- /var/run/docker.sock:/var/run/docker.sock
|
|
@ -1,11 +1,4 @@
|
|||
## Compose sample application
|
||||
|
||||
### Use with Docker Development Environments
|
||||
|
||||
You can open this sample in the Dev Environments feature of Docker Desktop version 4.12 or later.
|
||||
|
||||
[Open in Docker Dev Environments <img src="../open_in_new.svg" alt="Open in Docker Dev Environments" align="top"/>](https://open.docker.com/dashboard/dev-envs?url=https://github.com/docker/awesome-compose/tree/master/flask)
|
||||
|
||||
### Python/Flask application
|
||||
|
||||
Project structure:
|
||||
|
|
|
@ -1,8 +0,0 @@
|
|||
<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" fill="#54D1B0">
|
||||
<path
|
||||
d="M5.023 14.4711H5.0127V9.71269L11.7075 12.5098C11.7166 12.5136 11.7257 12.5172 11.7348 12.5207C11.8226 12.5622 11.9289 12.583 12.042 12.581C12.1551 12.583 12.2615 12.5622 12.3492 12.5207C12.3584 12.5172 12.3675 12.5136 12.3765 12.5098L19.0125 9.73729V14.4711H19.0021C19.009 14.5093 19.0125 14.5484 19.0125 14.588C19.0125 14.6005 19.0121 14.6128 19.0114 14.6251C18.9973 14.8804 18.8378 15.1069 18.5967 15.2117L12.2968 17.9413C12.2058 17.9802 12.1092 18 12.0126 18C11.9153 18 11.8187 17.9802 11.7277 17.9413L5.42779 15.2117C5.19236 15.1091 5.03453 14.8897 5.01479 14.641C5.0134 14.6234 5.0127 14.6058 5.0127 14.588C5.0127 14.5484 5.01621 14.5093 5.023 14.4711ZM18.7272 8.86192C18.6871 8.83329 18.6435 8.80857 18.5969 8.78842L12.297 6.05886C12.1157 5.98038 11.9092 5.98038 11.7279 6.05886L5.42802 8.78842C5.39 8.80489 5.354 8.82442 5.32029 8.84664L12.042 11.655L18.7272 8.86192Z"
|
||||
/>
|
||||
<path
|
||||
d="M6.06462 6.95773C5.93949 6.78761 5.71282 6.7275 5.51984 6.81327L3.54841 7.68946C3.27307 7.81183 3.08001 8.06184 3.02741 8.35276C3.02677 8.3563 3.02369 8.3589 3.02009 8.3589V8.3589C3.01601 8.3589 3.0127 8.36221 3.0127 8.3663V15.2024C3.0127 15.2058 3.01542 15.2085 3.01877 15.2085V15.2085C3.02254 15.2085 3.0254 15.2119 3.02478 15.2156C3.01681 15.2638 3.0127 15.3132 3.0127 15.3632C3.0127 15.3867 3.01361 15.41 3.01539 15.4332C3.04085 15.7623 3.24444 16.0526 3.54812 16.1884L11.6742 19.8C11.7916 19.8515 11.9161 19.8777 12.0416 19.8777C12.1663 19.8777 12.2909 19.8515 12.4082 19.8L14.2808 18.9677C14.5198 18.8615 14.5994 18.5615 14.4444 18.3507V18.3507C14.3306 18.1959 14.1244 18.1411 13.9487 18.2188L12.3373 18.9315C12.2334 18.9769 12.123 19 12.0125 19C11.9013 19 11.791 18.9769 11.687 18.9315L4.48709 15.747C4.21802 15.6273 4.03764 15.3713 4.01509 15.0811C4.0135 15.0607 4.0127 15.0401 4.0127 15.0194C4.0127 14.9753 4.01634 14.9318 4.0234 14.8893C4.02395 14.886 4.02142 14.883 4.01808 14.883V14.883C4.0151 14.883 4.0127 14.8806 4.0127 14.8776V8.84998C4.0127 8.84636 4.01563 8.84342 4.01925 8.84342V8.84342C4.02244 8.84342 4.02516 8.84112 4.02573 8.83799C4.07235 8.58148 4.2434 8.36105 4.48735 8.25315L5.8843 7.63529C6.14719 7.51901 6.23494 7.18929 6.06462 6.95773V6.95773ZM18.2951 16.8352C18.1416 16.6265 18.2207 16.3293 18.4577 16.2245L19.5372 15.747C19.8128 15.6247 19.9951 15.3604 20.0112 15.0627C20.012 15.0483 20.0124 15.0339 20.0124 15.0194C20.0124 14.9753 20.0088 14.9318 20.0017 14.8893C20.0012 14.886 20.0037 14.883 20.007 14.883V14.883C20.01 14.883 20.0124 14.8806 20.0124 14.8776V9.00055L20.0127 8.98001L20.0126 8.96926L20.0124 8.95947V8.84972C20.0124 8.84624 20.0096 8.84342 20.0061 8.84342V8.84342C20.0031 8.84342 20.0005 8.84122 19.9999 8.83821C19.9534 8.5816 19.7822 8.36108 19.5375 8.25315L12.3376 5.06867C12.1304 4.97711 11.8944 4.97711 11.6872 5.06867L10.4765 5.60419C10.2817 5.69035 10.0532 5.62954 9.92697 5.45796V5.45796C9.75514 5.22434 9.84334 4.89172 10.1083 4.77394L11.6745 4.07788C11.9083 3.97404 12.1747 3.97404 12.4085 4.07788L20.5346 7.68946C20.8108 7.81187 21.004 8.06198 21.0565 8.35301C21.0571 8.35641 21.0601 8.3589 21.0635 8.3589V8.3589C21.0675 8.3589 21.0706 8.36208 21.0706 8.366V8.49051L21.0708 8.50161L21.0709 8.5138C21.0709 8.52159 21.0708 8.52935 21.0706 8.5371V15.2024C21.0706 15.2058 21.0679 15.2085 21.0646 15.2085V15.2085C21.0608 15.2085 21.0579 15.2119 21.0585 15.2156C21.0665 15.2638 21.0706 15.3132 21.0706 15.3632C21.0706 15.3796 21.0702 15.396 21.0693 15.4123C21.051 15.75 20.8453 16.0497 20.5343 16.1884L18.7861 16.9654C18.6122 17.0427 18.4079 16.9885 18.2951 16.8352V16.8352Z"
|
||||
/>
|
||||
</svg>
|
Before Width: | Height: | Size: 3.5 KiB |
13
icon_wasm.svg
Normal file
13
icon_wasm.svg
Normal file
|
@ -0,0 +1,13 @@
|
|||
<svg id="WA-icon" xmlns="http://www.w3.org/2000/svg" width="144" height="111" viewBox="0 0 1440 1110">
|
||||
<defs>
|
||||
<style>
|
||||
.cls-1 {
|
||||
fill: #6f45f9;
|
||||
fill-rule: evenodd;
|
||||
}
|
||||
</style>
|
||||
</defs>
|
||||
<path id="shape_4" data-name="shape 4" class="cls-1" d="M445,280H651v7s0.437,32.383,29,49c30.515,17.752,62.137,4.583,72-4,10.362-9.017,22.2-23.3,23-45v-7H981V816H445V280ZM569,567h36l24,128,30-128h33l27,128,28-127h35L737,759H702L675,631,646,759H610ZM776,759l46-191h57l55,191H897l-12-42H820l-9,42H776Z" transform="translate(0.594 9.312)"/>
|
||||
<path id="shape_1" data-name="shape 1" class="cls-1" d="M827,685.471l16-71h15l19,71H827Z" transform="translate(0.594 9.312)"/>
|
||||
<path id="shape_3" data-name="shape 3" class="cls-1" d="M323,232.471l-122,54s-32,12.311-32,51v412s-4.458,38.615,29,54,497,221,497,221,22.409,11.15,46,1,116-51,116-51,14.081-5.669,14-22c-0.088-17.6-16.3-33.023-36-24s-96,43-96,43-17.573,10.1-37,2-449-198-449-198-24-11.257-24-40v-374a42.353,42.353,0,0,1,25-38c25.972-12.225,88-39,88-39s18-5.765,18-26C360,237.118,338.709,225.966,323,232.471Zm284-127,93-41s19.94-8.9,51,5,485,216,485,216,34,14.168,34,51v422s0.85,30.084-26,43-116,53-116,53-14.98,4.522-25-7-8.79-32.833,5-39,67-29,67-29l8-4s23-12.024,23-46v-369s1.61-26.142-28-39-437-194-437-194-21.48-9.931-40-2-77,34-77,34-22.162,7.988-33-8S584.324,115.515,607,105.471Z" transform="translate(0.594 9.312)"/>
|
||||
</svg>
|
After Width: | Height: | Size: 1.4 KiB |
|
@ -1,38 +0,0 @@
|
|||
services:
|
||||
backend:
|
||||
build:
|
||||
context: backend
|
||||
target: dev-envs
|
||||
restart: always
|
||||
secrets:
|
||||
- db-password
|
||||
depends_on: ['db']
|
||||
environment:
|
||||
- ASPNETCORE_URLS=http://+:8000
|
||||
volumes:
|
||||
- /var/run/docker.sock:/var/run/docker.sock
|
||||
|
||||
db:
|
||||
image: mariadb:10-focal
|
||||
command: '--default-authentication-plugin=mysql_native_password'
|
||||
restart: always
|
||||
secrets:
|
||||
- db-password
|
||||
volumes:
|
||||
- db-data:/var/lib/mysql
|
||||
environment:
|
||||
- MYSQL_DATABASE=example
|
||||
- MYSQL_ROOT_PASSWORD_FILE=/run/secrets/db-password
|
||||
|
||||
proxy:
|
||||
build: proxy
|
||||
ports:
|
||||
- 80:80
|
||||
depends_on:
|
||||
- backend
|
||||
|
||||
volumes:
|
||||
db-data:
|
||||
secrets:
|
||||
db-password:
|
||||
file: db/password.txt
|
|
@ -1,12 +1,5 @@
|
|||
## Compose sample application
|
||||
|
||||
### Use with Docker Development Environments
|
||||
|
||||
You can open this sample in the Dev Environments feature of Docker Desktop version 4.12 or later.
|
||||
|
||||
[Open in Docker Dev Environments <img src="../open_in_new.svg" alt="Open in Docker Dev Environments" align="top"/>](https://open.docker.com/dashboard/dev-envs?url=https://github.com/docker/awesome-compose/tree/master/nginx-aspnet-mysql)
|
||||
|
||||
### ASP.NET server with an Nginx proxy and a MySQL database
|
||||
### ASP.NET server with a Nginx proxy and a MySQL database
|
||||
|
||||
Project structure:
|
||||
```
|
||||
|
|
|
@ -1,27 +0,0 @@
|
|||
services:
|
||||
web:
|
||||
image: nginx
|
||||
volumes:
|
||||
- ./nginx/nginx.conf:/tmp/nginx.conf
|
||||
environment:
|
||||
- FLASK_SERVER_ADDR=backend:9091
|
||||
command: /bin/bash -c "envsubst < /tmp/nginx.conf > /etc/nginx/conf.d/default.conf && nginx -g 'daemon off;'"
|
||||
ports:
|
||||
- 80:80
|
||||
depends_on:
|
||||
- backend
|
||||
|
||||
backend:
|
||||
build:
|
||||
context: flask
|
||||
target: dev-envs
|
||||
stop_signal: SIGINT
|
||||
environment:
|
||||
- FLASK_SERVER_PORT=9091
|
||||
volumes:
|
||||
- /var/run/docker.sock:/var/run/docker.sock
|
||||
depends_on:
|
||||
- mongo
|
||||
|
||||
mongo:
|
||||
image: mongo
|
|
@ -1,11 +1,4 @@
|
|||
## Compose sample application
|
||||
|
||||
### Use with Docker Development Environments
|
||||
|
||||
You can open this sample in the Dev Environments feature of Docker Desktop version 4.12 or later.
|
||||
|
||||
[Open in Docker Dev Environments <img src="../open_in_new.svg" alt="Open in Docker Dev Environments" align="top"/>](https://open.docker.com/dashboard/dev-envs?url=https://github.com/docker/awesome-compose/tree/master/nginx-flask-mongo)
|
||||
|
||||
### Python/Flask application with Nginx proxy and a Mongo database
|
||||
|
||||
Project structure:
|
||||
|
|
|
@ -1,61 +0,0 @@
|
|||
services:
|
||||
db:
|
||||
image: mariadb:10-focal
|
||||
command: '--default-authentication-plugin=mysql_native_password'
|
||||
restart: always
|
||||
healthcheck:
|
||||
test: ["CMD", "mysqladmin", "ping", "-h", "127.0.0.1", "--silent"]
|
||||
interval: 3s
|
||||
retries: 5
|
||||
start_period: 30s
|
||||
secrets:
|
||||
- db-password
|
||||
volumes:
|
||||
- db-data:/var/lib/mysql
|
||||
networks:
|
||||
- backnet
|
||||
environment:
|
||||
- MYSQL_DATABASE=example
|
||||
- MYSQL_ROOT_PASSWORD_FILE=/run/secrets/db-password
|
||||
expose:
|
||||
- 3306
|
||||
- 33060
|
||||
|
||||
backend:
|
||||
build:
|
||||
context: backend
|
||||
target: dev-envs
|
||||
restart: always
|
||||
volumes:
|
||||
- /var/run/docker.sock:/var/run/docker.sock
|
||||
secrets:
|
||||
- db-password
|
||||
ports:
|
||||
- 8000:8000
|
||||
networks:
|
||||
- backnet
|
||||
- frontnet
|
||||
depends_on:
|
||||
db:
|
||||
condition: service_healthy
|
||||
|
||||
proxy:
|
||||
build: proxy
|
||||
restart: always
|
||||
ports:
|
||||
- 80:80
|
||||
depends_on:
|
||||
- backend
|
||||
networks:
|
||||
- frontnet
|
||||
|
||||
volumes:
|
||||
db-data:
|
||||
|
||||
secrets:
|
||||
db-password:
|
||||
file: db/password.txt
|
||||
|
||||
networks:
|
||||
backnet:
|
||||
frontnet:
|
|
@ -1,11 +1,4 @@
|
|||
## Compose sample application
|
||||
|
||||
### Use with Docker Development Environments
|
||||
|
||||
You can open this sample in the Dev Environments feature of Docker Desktop version 4.12 or later.
|
||||
|
||||
[Open in Docker Dev Environments <img src="../open_in_new.svg" alt="Open in Docker Dev Environments" align="top"/>](https://open.docker.com/dashboard/dev-envs?url=https://github.com/docker/awesome-compose/tree/master/nginx-flask-mysql)
|
||||
|
||||
### Python/Flask with Nginx proxy and MySQL database
|
||||
|
||||
Project structure:
|
||||
|
|
|
@ -1,50 +0,0 @@
|
|||
services:
|
||||
backend:
|
||||
build:
|
||||
context: backend
|
||||
target: dev-envs
|
||||
volumes:
|
||||
- /var/run/docker.sock:/var/run/docker.sock
|
||||
secrets:
|
||||
- db-password
|
||||
depends_on:
|
||||
db:
|
||||
condition: service_healthy
|
||||
|
||||
db:
|
||||
image: mariadb:10-focal
|
||||
command: '--default-authentication-plugin=mysql_native_password'
|
||||
restart: always
|
||||
healthcheck:
|
||||
test: ["CMD", "mysqladmin", "ping", "-h", "127.0.0.1", "--silent"]
|
||||
interval: 3s
|
||||
retries: 5
|
||||
start_period: 30s
|
||||
secrets:
|
||||
- db-password
|
||||
volumes:
|
||||
- db-data:/var/lib/mysql
|
||||
environment:
|
||||
- MYSQL_DATABASE=example
|
||||
- MYSQL_ROOT_PASSWORD_FILE=/run/secrets/db-password
|
||||
expose:
|
||||
- 3306
|
||||
|
||||
proxy:
|
||||
image: nginx
|
||||
volumes:
|
||||
- type: bind
|
||||
source: ./proxy/nginx.conf
|
||||
target: /etc/nginx/conf.d/default.conf
|
||||
read_only: true
|
||||
ports:
|
||||
- 80:80
|
||||
depends_on:
|
||||
- backend
|
||||
|
||||
volumes:
|
||||
db-data:
|
||||
|
||||
secrets:
|
||||
db-password:
|
||||
file: db/password.txt
|
|
@ -1,12 +1,5 @@
|
|||
## Compose sample application
|
||||
|
||||
### Use with Docker Development Environments
|
||||
|
||||
You can open this sample in the Dev Environments feature of Docker Desktop version 4.12 or later.
|
||||
|
||||
[Open in Docker Dev Environments <img src="../open_in_new.svg" alt="Open in Docker Dev Environments" align="top"/>](https://open.docker.com/dashboard/dev-envs?url=https://github.com/docker/awesome-compose/tree/master/nginx-golang-mysql)
|
||||
|
||||
### Go server with an Nginx proxy and a MariaDB/MySQL database
|
||||
### Go server with a Nginx proxy and a MariaDB/MySQL database
|
||||
|
||||
Project structure:
|
||||
```
|
||||
|
|
|
@ -1,50 +0,0 @@
|
|||
services:
|
||||
backend:
|
||||
build:
|
||||
context: backend
|
||||
target: dev-envs
|
||||
volumes:
|
||||
- /var/run/docker.sock:/var/run/docker.sock
|
||||
secrets:
|
||||
- db-password
|
||||
depends_on:
|
||||
db:
|
||||
condition: service_healthy
|
||||
|
||||
db:
|
||||
image: postgres
|
||||
restart: always
|
||||
user: postgres
|
||||
secrets:
|
||||
- db-password
|
||||
volumes:
|
||||
- db-data:/var/lib/postgresql/data
|
||||
environment:
|
||||
- POSTGRES_DB=example
|
||||
- POSTGRES_PASSWORD_FILE=/run/secrets/db-password
|
||||
expose:
|
||||
- 5432
|
||||
healthcheck:
|
||||
test: [ "CMD", "pg_isready" ]
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
|
||||
proxy:
|
||||
image: nginx
|
||||
volumes:
|
||||
- type: bind
|
||||
source: ./proxy/nginx.conf
|
||||
target: /etc/nginx/conf.d/default.conf
|
||||
read_only: true
|
||||
ports:
|
||||
- 80:80
|
||||
depends_on:
|
||||
- backend
|
||||
|
||||
volumes:
|
||||
db-data:
|
||||
|
||||
secrets:
|
||||
db-password:
|
||||
file: db/password.txt
|
|
@ -1,12 +1,5 @@
|
|||
## Compose sample application
|
||||
|
||||
### Use with Docker Development Environments
|
||||
|
||||
You can open this sample in the Dev Environments feature of Docker Desktop version 4.12 or later.
|
||||
|
||||
[Open in Docker Dev Environments <img src="../open_in_new.svg" alt="Open in Docker Dev Environments" align="top"/>](https://open.docker.com/dashboard/dev-envs?url=https://github.com/docker/awesome-compose/tree/master/nginx-golang-postgres)
|
||||
|
||||
### Go server with an Nginx proxy and a Postgres database
|
||||
### Go server with a Nginx proxy and a Postgres database
|
||||
|
||||
Project structure:
|
||||
```
|
||||
|
|
|
@ -1,19 +0,0 @@
|
|||
services:
|
||||
proxy:
|
||||
image: nginx
|
||||
volumes:
|
||||
- type: bind
|
||||
source: ./proxy/nginx.conf
|
||||
target: /etc/nginx/conf.d/default.conf
|
||||
read_only: true
|
||||
ports:
|
||||
- 80:80
|
||||
depends_on:
|
||||
- backend
|
||||
|
||||
backend:
|
||||
build:
|
||||
context: backend
|
||||
target: dev-envs
|
||||
volumes:
|
||||
- /var/run/docker.sock:/var/run/docker.sock
|
|
@ -1,11 +1,4 @@
|
|||
## Compose sample application
|
||||
|
||||
### Use with Docker Development Environments
|
||||
|
||||
You can open this sample in the Dev Environments feature of Docker Desktop version 4.12 or later.
|
||||
|
||||
[Open in Docker Dev Environments <img src="../open_in_new.svg" alt="Open in Docker Dev Environments" align="top"/>](https://open.docker.com/dashboard/dev-envs?url=https://github.com/docker/awesome-compose/tree/master/nginx-golang)
|
||||
|
||||
### NGINX proxy with Go backend
|
||||
|
||||
Project structure:
|
||||
|
|
|
@ -1,43 +0,0 @@
|
|||
services:
|
||||
frontend:
|
||||
build:
|
||||
context: frontend
|
||||
target: dev-envs
|
||||
ports:
|
||||
- 3000:3000
|
||||
stdin_open: true
|
||||
volumes:
|
||||
- /var/run/docker.sock:/var/run/docker.sock
|
||||
restart: always
|
||||
networks:
|
||||
- react-express
|
||||
depends_on:
|
||||
- backend
|
||||
|
||||
backend:
|
||||
restart: always
|
||||
build:
|
||||
context: backend
|
||||
target: dev-envs
|
||||
volumes:
|
||||
- /var/run/docker.sock:/var/run/docker.sock
|
||||
depends_on:
|
||||
- mongo
|
||||
networks:
|
||||
- express-mongo
|
||||
- react-express
|
||||
expose:
|
||||
- 3000
|
||||
mongo:
|
||||
container_name: mongo
|
||||
restart: always
|
||||
image: mongo:4.2.0
|
||||
volumes:
|
||||
- ./data:/data/db
|
||||
networks:
|
||||
- express-mongo
|
||||
expose:
|
||||
- 27017
|
||||
networks:
|
||||
react-express:
|
||||
express-mongo:
|
|
@ -1,11 +1,4 @@
|
|||
## Compose sample application
|
||||
|
||||
### Use with Docker Development Environments
|
||||
|
||||
You can open this sample in the Dev Environments feature of Docker Desktop version 4.12 or later.
|
||||
|
||||
[Open in Docker Dev Environments <img src="../open_in_new.svg" alt="Open in Docker Dev Environments" align="top"/>](https://open.docker.com/dashboard/dev-envs?url=https://github.com/docker/awesome-compose/tree/master/react-express-mongodb)
|
||||
|
||||
### React application with a NodeJS backend and a MongoDB database
|
||||
|
||||
Project structure:
|
||||
|
|
|
@ -9,7 +9,6 @@ services:
|
|||
volumes:
|
||||
- ./frontend:/usr/src/app
|
||||
- /usr/src/app/node_modules
|
||||
container_name: frontend
|
||||
restart: always
|
||||
networks:
|
||||
- react-express
|
||||
|
@ -17,7 +16,6 @@ services:
|
|||
- backend
|
||||
|
||||
backend:
|
||||
container_name: backend
|
||||
restart: always
|
||||
build:
|
||||
context: backend
|
||||
|
@ -33,11 +31,10 @@ services:
|
|||
expose:
|
||||
- 3000
|
||||
mongo:
|
||||
container_name: mongo
|
||||
restart: always
|
||||
image: mongo:4.2.0
|
||||
volumes:
|
||||
- ./data:/data/db
|
||||
- mongo_data:/data/db
|
||||
networks:
|
||||
- express-mongo
|
||||
expose:
|
||||
|
@ -45,3 +42,6 @@ services:
|
|||
networks:
|
||||
react-express:
|
||||
express-mongo:
|
||||
|
||||
volumes:
|
||||
mongo_data:
|
||||
|
|
|
@ -1,64 +0,0 @@
|
|||
services:
|
||||
backend:
|
||||
build:
|
||||
args:
|
||||
- NODE_ENV=development
|
||||
context: backend
|
||||
target: dev-envs
|
||||
command: npm run start-watch
|
||||
environment:
|
||||
- DATABASE_DB=example
|
||||
- DATABASE_USER=root
|
||||
- DATABASE_PASSWORD=/run/secrets/db-password
|
||||
- DATABASE_HOST=db
|
||||
- NODE_ENV=development
|
||||
ports:
|
||||
- 80:80
|
||||
- 9229:9229
|
||||
- 9230:9230
|
||||
secrets:
|
||||
- db-password
|
||||
volumes:
|
||||
- /var/run/docker.sock:/var/run/docker.sock
|
||||
networks:
|
||||
- public
|
||||
- private
|
||||
depends_on:
|
||||
- db
|
||||
db:
|
||||
# We use a mariadb image which supports both amd64 & arm64 architecture
|
||||
image: mariadb:10.6.4-focal
|
||||
# If you really want to use MySQL, uncomment the following line
|
||||
#image: mysql:8.0.27
|
||||
command: '--default-authentication-plugin=mysql_native_password'
|
||||
restart: always
|
||||
secrets:
|
||||
- db-password
|
||||
volumes:
|
||||
- db-data:/var/lib/mysql
|
||||
networks:
|
||||
- private
|
||||
environment:
|
||||
- MYSQL_DATABASE=example
|
||||
- MYSQL_ROOT_PASSWORD_FILE=/run/secrets/db-password
|
||||
frontend:
|
||||
build:
|
||||
context: frontend
|
||||
target: dev-envs
|
||||
ports:
|
||||
- 3000:3000
|
||||
volumes:
|
||||
- /var/run/docker.sock:/var/run/docker.sock
|
||||
networks:
|
||||
- public
|
||||
depends_on:
|
||||
- backend
|
||||
networks:
|
||||
public:
|
||||
private:
|
||||
volumes:
|
||||
back-notused:
|
||||
db-data:
|
||||
secrets:
|
||||
db-password:
|
||||
file: db/password.txt
|
|
@ -1,11 +1,4 @@
|
|||
## Compose sample application
|
||||
|
||||
### Use with Docker Development Environments
|
||||
|
||||
You can open this sample in the Dev Environments feature of Docker Desktop version 4.12 or later.
|
||||
|
||||
[Open in Docker Dev Environments <img src="../open_in_new.svg" alt="Open in Docker Dev Environments" align="top"/>](https://open.docker.com/dashboard/dev-envs?url=https://github.com/docker/awesome-compose/tree/master/react-express-mysql)
|
||||
|
||||
### React application with a NodeJS backend and a MySQL database
|
||||
|
||||
Project structure:
|
||||
|
|
|
@ -1,61 +0,0 @@
|
|||
services:
|
||||
backend:
|
||||
build:
|
||||
context: backend
|
||||
target: dev-envs
|
||||
restart: always
|
||||
secrets:
|
||||
- db-password
|
||||
environment:
|
||||
MYSQL_HOST: db
|
||||
volumes:
|
||||
- /var/run/docker.sock:/var/run/docker.sock
|
||||
networks:
|
||||
- react-spring
|
||||
- spring-mysql
|
||||
depends_on:
|
||||
db:
|
||||
condition: service_healthy
|
||||
db:
|
||||
# We use a mariadb image which supports both amd64 & arm64 architecture
|
||||
image: mariadb:10.6.4-focal
|
||||
# If you really want to use MySQL, uncomment the following line
|
||||
#image: mysql:8.0.19
|
||||
environment:
|
||||
- MYSQL_DATABASE=example
|
||||
- MYSQL_ROOT_PASSWORD_FILE=/run/secrets/db-password
|
||||
restart: always
|
||||
healthcheck:
|
||||
test: ["CMD", "mysqladmin", "ping", "-h", "127.0.0.1", "--silent"]
|
||||
interval: 3s
|
||||
retries: 5
|
||||
start_period: 30s
|
||||
secrets:
|
||||
- db-password
|
||||
volumes:
|
||||
- db-data:/var/lib/mysql
|
||||
networks:
|
||||
- spring-mysql
|
||||
frontend:
|
||||
build:
|
||||
context: frontend
|
||||
target: dev-envs
|
||||
ports:
|
||||
- 3000:3000
|
||||
volumes:
|
||||
- /var/run/docker.sock:/var/run/docker.sock
|
||||
networks:
|
||||
- react-spring
|
||||
depends_on:
|
||||
- backend
|
||||
expose:
|
||||
- 3306
|
||||
- 33060
|
||||
volumes:
|
||||
db-data: {}
|
||||
secrets:
|
||||
db-password:
|
||||
file: db/password.txt
|
||||
networks:
|
||||
react-spring: {}
|
||||
spring-mysql: {}
|
|
@ -1,11 +1,4 @@
|
|||
## Compose sample application
|
||||
|
||||
### Use with Docker Development Environments
|
||||
|
||||
You can open this sample in the Dev Environments feature of Docker Desktop version 4.12 or later.
|
||||
|
||||
[Open in Docker Dev Environments <img src="../open_in_new.svg" alt="Open in Docker Dev Environments" align="top"/>](https://open.docker.com/dashboard/dev-envs?url=https://github.com/docker/awesome-compose/tree/master/react-java-mysql)
|
||||
|
||||
### React application with a Spring backend and a MySQL database
|
||||
|
||||
Project structure:
|
||||
|
|
|
@ -1,11 +0,0 @@
|
|||
services:
|
||||
frontend:
|
||||
build:
|
||||
context: .
|
||||
target: dev-envs
|
||||
container_name: frontend
|
||||
ports:
|
||||
- "80:3000"
|
||||
- "3000:3000"
|
||||
volumes:
|
||||
- /var/run/docker.sock:/var/run/docker.sock
|
|
@ -1,11 +1,4 @@
|
|||
## Compose sample application
|
||||
|
||||
### Use with Docker Development Environments
|
||||
|
||||
You can open this sample in the Dev Environments feature of Docker Desktop version 4.12 or later.
|
||||
|
||||
[Open in Docker Dev Environments <img src="../open_in_new.svg" alt="Open in Docker Dev Environments" align="top"/>](https://open.docker.com/dashboard/dev-envs?url=https://github.com/docker/awesome-compose/tree/master/react-nginx)
|
||||
|
||||
### An project deploy React Application with Nginx
|
||||
|
||||
Project structure:
|
||||
|
|
|
@ -1,51 +0,0 @@
|
|||
name: react-rust-postgres
|
||||
services:
|
||||
frontend:
|
||||
build:
|
||||
context: ../frontend
|
||||
target: dev-envs
|
||||
networks:
|
||||
- client-side
|
||||
ports:
|
||||
- 3000:3000
|
||||
volumes:
|
||||
- /var/run/docker.sock:/var/run/docker.sock
|
||||
|
||||
backend:
|
||||
build:
|
||||
context: ../backend
|
||||
target: dev-envs
|
||||
environment:
|
||||
- RUST_LOG=debug
|
||||
- PG_DBNAME=postgres
|
||||
- PG_HOST=db
|
||||
- PG_USER=postgres
|
||||
- PG_PASSWORD=mysecretpassword
|
||||
- ADDRESS=0.0.0.0:8000
|
||||
networks:
|
||||
- client-side
|
||||
- server-side
|
||||
volumes:
|
||||
- /var/run/docker.sock:/var/run/docker.sock
|
||||
depends_on:
|
||||
- db
|
||||
|
||||
db:
|
||||
image: postgres:12-alpine
|
||||
restart: always
|
||||
environment:
|
||||
- POSTGRES_PASSWORD=mysecretpassword
|
||||
networks:
|
||||
- server-side
|
||||
ports:
|
||||
- 5432:5432
|
||||
volumes:
|
||||
- db-data:/var/lib/postgresql/data
|
||||
|
||||
networks:
|
||||
client-side: {}
|
||||
server-side: {}
|
||||
|
||||
volumes:
|
||||
backend-cache: {}
|
||||
db-data: {}
|
|
@ -1,11 +1,4 @@
|
|||
## Compose sample application
|
||||
|
||||
### Use with Docker Development Environments
|
||||
|
||||
You can open this sample in the Dev Environments feature of Docker Desktop version 4.12 or later.
|
||||
|
||||
[Open in Docker Dev Environments <img src="../open_in_new.svg" alt="Open in Docker Dev Environments" align="top"/>](https://open.docker.com/dashboard/dev-envs?url=https://github.com/docker/awesome-compose/tree/master/react-rust-postgres)
|
||||
|
||||
### React application with a Rust backend and a Postgresql database
|
||||
|
||||
Project structure:
|
||||
|
|
|
@ -1,32 +0,0 @@
|
|||
services:
|
||||
backend:
|
||||
build:
|
||||
context: backend
|
||||
target: dev-envs
|
||||
ports:
|
||||
- 8080:8080
|
||||
secrets:
|
||||
- db-password
|
||||
volumes:
|
||||
- /var/run/docker.sock:/var/run/docker.sock
|
||||
db:
|
||||
# We use a mariadb image which supports both amd64 & arm64 architecture
|
||||
image: mariadb:10.6.4-focal
|
||||
# If you really want to use MySQL, uncomment the following line
|
||||
#image: mysql:8.0.27
|
||||
restart: always
|
||||
secrets:
|
||||
- db-password
|
||||
volumes:
|
||||
- db-data:/var/lib/mysql
|
||||
environment:
|
||||
- MYSQL_DATABASE=example
|
||||
- MYSQL_ROOT_PASSWORD_FILE=/run/secrets/db-password
|
||||
expose:
|
||||
- 3306
|
||||
- 33060
|
||||
volumes:
|
||||
db-data:
|
||||
secrets:
|
||||
db-password:
|
||||
file: db/password.txt
|
|
@ -1,11 +1,4 @@
|
|||
## Compose sample application
|
||||
|
||||
### Use with Docker Development Environments
|
||||
|
||||
You can open this sample in the Dev Environments feature of Docker Desktop version 4.12 or later.
|
||||
|
||||
[Open in Docker Dev Environments <img src="../open_in_new.svg" alt="Open in Docker Dev Environments" align="top"/>](https://open.docker.com/dashboard/dev-envs?url=https://github.com/docker/awesome-compose/tree/master/sparkjava-mysql)
|
||||
|
||||
### Java Spark application with MySQL database
|
||||
|
||||
Project structure:
|
||||
|
|
|
@ -1,9 +0,0 @@
|
|||
services:
|
||||
sparkjava:
|
||||
build:
|
||||
context: sparkjava
|
||||
target: dev-envs
|
||||
ports:
|
||||
- 8080:8080
|
||||
volumes:
|
||||
- /var/run/docker.sock:/var/run/docker.sock
|
|
@ -1,11 +1,4 @@
|
|||
## Compose sample application
|
||||
|
||||
### Use with Docker Development Environments
|
||||
|
||||
You can open this sample in the Dev Environments feature of Docker Desktop version 4.12 or later.
|
||||
|
||||
[Open in Docker Dev Environments <img src="../open_in_new.svg" alt="Open in Docker Dev Environments" align="top"/>](https://open.docker.com/dashboard/dev-envs?url=https://github.com/docker/awesome-compose/tree/master/sparkjava)
|
||||
|
||||
### Spark Java
|
||||
|
||||
Project structure:
|
||||
|
|
|
@ -1,34 +0,0 @@
|
|||
services:
|
||||
backend:
|
||||
build:
|
||||
context: backend
|
||||
target: dev-envs
|
||||
ports:
|
||||
- 8080:8080
|
||||
environment:
|
||||
- POSTGRES_DB=example
|
||||
networks:
|
||||
- spring-postgres
|
||||
volumes:
|
||||
- /var/run/docker.sock:/var/run/docker.sock
|
||||
db:
|
||||
image: postgres
|
||||
restart: always
|
||||
secrets:
|
||||
- db-password
|
||||
volumes:
|
||||
- db-data:/var/lib/postgresql/data
|
||||
networks:
|
||||
- spring-postgres
|
||||
environment:
|
||||
- POSTGRES_DB=example
|
||||
- POSTGRES_PASSWORD_FILE=/run/secrets/db-password
|
||||
expose:
|
||||
- 5432
|
||||
volumes:
|
||||
db-data:
|
||||
secrets:
|
||||
db-password:
|
||||
file: db/password.txt
|
||||
networks:
|
||||
spring-postgres:
|
|
@ -1,11 +1,4 @@
|
|||
## Compose sample application
|
||||
|
||||
### Use with Docker Development Environments
|
||||
|
||||
You can open this sample in the Dev Environments feature of Docker Desktop version 4.12 or later.
|
||||
|
||||
[Open in Docker Dev Environments <img src="../open_in_new.svg" alt="Open in Docker Dev Environments" align="top"/>](https://open.docker.com/dashboard/dev-envs?url=https://github.com/docker/awesome-compose/tree/master/spring-postgres)
|
||||
|
||||
### Java application with Spring framework and a Postgres database
|
||||
|
||||
Project structure:
|
||||
|
|
|
@ -1,22 +0,0 @@
|
|||
services:
|
||||
frontend:
|
||||
image: traefik:2.6
|
||||
command: --providers.docker --entrypoints.web.address=:80 --providers.docker.exposedbydefault=false
|
||||
ports:
|
||||
# The HTTP port
|
||||
- "80:80"
|
||||
volumes:
|
||||
# So that Traefik can listen to the Docker events
|
||||
- /var/run/docker.sock:/var/run/docker.sock
|
||||
depends_on:
|
||||
- backend
|
||||
backend:
|
||||
build:
|
||||
context: backend
|
||||
target: dev-envs
|
||||
volumes:
|
||||
- /var/run/docker.sock:/var/run/docker.sock
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
- "traefik.http.routers.go.rule=Path(`/`)"
|
||||
- "traefik.http.services.go.loadbalancer.server.port=80"
|
|
@ -1,11 +1,4 @@
|
|||
## Compose sample application
|
||||
|
||||
### Use with Docker Development Environments
|
||||
|
||||
You can open this sample in the Dev Environments feature of Docker Desktop version 4.12 or later.
|
||||
|
||||
[Open in Docker Dev Environments <img src="../open_in_new.svg" alt="Open in Docker Dev Environments" align="top"/>](https://open.docker.com/dashboard/dev-envs?url=https://github.com/docker/awesome-compose/tree/master/traefik-golang)
|
||||
|
||||
### TRAEFIK proxy with GO backend
|
||||
|
||||
Project structure:
|
||||
|
|
|
@ -1,9 +0,0 @@
|
|||
services:
|
||||
web:
|
||||
build:
|
||||
context: vuejs
|
||||
target: dev-envs
|
||||
ports:
|
||||
- 8080:8080
|
||||
volumes:
|
||||
- /var/run/docker.sock:/var/run/docker.sock
|
|
@ -1,11 +1,4 @@
|
|||
## Compose sample application
|
||||
|
||||
### Use with Docker Development Environments
|
||||
|
||||
You can open this sample in the Dev Environments feature of Docker Desktop version 4.12 or later.
|
||||
|
||||
[Open in Docker Dev Environments <img src="../open_in_new.svg" alt="Open in Docker Dev Environments" align="top"/>](https://open.docker.com/dashboard/dev-envs?url=https://github.com/docker/awesome-compose/tree/master/vuejs)
|
||||
|
||||
### VueJS
|
||||
|
||||
Project structure:
|
||||
|
|
110
wasmedge-kafka-mysql/README.md
Normal file
110
wasmedge-kafka-mysql/README.md
Normal file
|
@ -0,0 +1,110 @@
|
|||
# Compose sample application
|
||||
|
||||

|
||||
|
||||
This sample demonstrates a WebAssembly (Wasm) microservice written in Rust. It subscribes to a Kafka queue topic on a Redpanda server, and then transforms and saves each message into a MySQL (MariaDB) database table. The microservice is compiled into Wasm and runs in the WasmEdge runtime, which is a secure and lightweight alternative to natively compiled Rust apps in Linux containers.
|
||||
|
||||
## WasmEdge server with Redpanda and MySQL database
|
||||
|
||||
Project structure:
|
||||
|
||||
```
|
||||
.
|
||||
+-- compose.yml
|
||||
|-- etl
|
||||
|-- Dockerfile
|
||||
|-- Cargo.toml
|
||||
+-- src
|
||||
|-- main.rs
|
||||
|-- kafka
|
||||
|-- order.json
|
||||
|-- db
|
||||
|-- db-password.txt
|
||||
```
|
||||
|
||||
The [compose.yml](compose.yml) is as follows.
|
||||
|
||||
```yaml
|
||||
services:
|
||||
redpanda:
|
||||
image: docker.redpanda.com/vectorized/redpanda:v22.2.2
|
||||
command:
|
||||
- redpanda start
|
||||
- --smp 1
|
||||
- --overprovisioned
|
||||
- --node-id 0
|
||||
- --kafka-addr PLAINTEXT://0.0.0.0:29092,OUTSIDE://0.0.0.0:9092
|
||||
- --advertise-kafka-addr PLAINTEXT://redpanda:29092,OUTSIDE://redpanda:9092
|
||||
- --pandaproxy-addr 0.0.0.0:8082
|
||||
- --advertise-pandaproxy-addr localhost:8082
|
||||
ports:
|
||||
- 8081:8081
|
||||
- 8082:8082
|
||||
- 9092:9092
|
||||
- 9644:9644
|
||||
- 29092:29092
|
||||
volumes:
|
||||
- ./kafka:/app
|
||||
|
||||
etl:
|
||||
image: etl-kafka
|
||||
build:
|
||||
context: etl
|
||||
platforms:
|
||||
- wasi/wasm32
|
||||
environment:
|
||||
DATABASE_URL: mysql://root:whalehello@db:3306/mysql
|
||||
KAFKA_URL: kafka://redpanda:9092/order
|
||||
RUST_BACKTRACE: full
|
||||
RUST_LOG: info
|
||||
restart: unless-stopped
|
||||
runtime: io.containerd.wasmedge.v1
|
||||
|
||||
db:
|
||||
image: mariadb:10.9
|
||||
environment:
|
||||
MYSQL_ROOT_PASSWORD: whalehello
|
||||
```
|
||||
|
||||
The compose file defines an application with three services `redpanda`, `etl` and `db`. The `redpanda` service is a Kafka-compatible messaging server that produces messages in a queue topic. The `etl` service, in the WasmEdge container that subscribes to the queue topic and receives incoming messages. Each incoming message is parsed and stored in the `db` MySQL (MariaDB) database server.
|
||||
|
||||
## Deploy with docker compose
|
||||
|
||||
```bash
|
||||
$ docker compose up -d
|
||||
...
|
||||
⠿ Network wasmedge-kafka-mysql_default Created 0.1s
|
||||
⠿ Container wasmedge-kafka-mysql-redpanda-1 Created 0.3s
|
||||
⠿ Container wasmedge-kafka-mysql-etl-1 Created 0.3s
|
||||
⠿ Container wasmedge-kafka-mysql-db-1 Created 0.3s
|
||||
```
|
||||
|
||||
## Expected result
|
||||
|
||||
```bash
|
||||
$ docker compose ps
|
||||
NAME COMMAND SERVICE STATUS PORTS
|
||||
wasmedge-kafka-mysql-db-1 "docker-entrypoint.s…" db running 3306/tcp
|
||||
wasmedge-kafka-mysql-etl-1 "kafka.wasm" etl running
|
||||
wasmedge-kafka-mysql-redpanda-1 "/entrypoint.sh 'red…" redpanda running 0.0.0.0:8081-8082->8081-8082/tcp, :::8081-8082->8081-8082/tcp, 0.0.0.0:9092->9092/tcp, :::9092->9092/tcp, 0.0.0.0:9644->9644/tcp, :::9644->9644/tcp, 0.0.0.0:29092->29092/tcp, :::29092->29092/tcp
|
||||
```
|
||||
|
||||
After the application starts,
|
||||
log into the Redpanda container and send a message to the queue topic `order` as follows.
|
||||
|
||||
```bash
|
||||
$ docker compose exec redpanda /bin/bash
|
||||
redpanda@1add2615774b:/$ cd /app
|
||||
redpanda@1add2615774b:/app$ cat order.json | rpk topic produce order
|
||||
Produced to partition 0 at offset 0 with timestamp 1667922788523.
|
||||
```
|
||||
|
||||
To see the data in the database container, you can use the following commands.
|
||||
|
||||
```bash
|
||||
$ docker compose exec db /bin/bash
|
||||
root@c97c472db02e:/# mysql -u root -pwhalehello mysql
|
||||
mysql> select * from orders;
|
||||
... ...
|
||||
```
|
||||
|
36
wasmedge-kafka-mysql/compose.yml
Normal file
36
wasmedge-kafka-mysql/compose.yml
Normal file
|
@ -0,0 +1,36 @@
|
|||
services:
|
||||
redpanda:
|
||||
image: docker.redpanda.com/vectorized/redpanda:v22.2.2
|
||||
command:
|
||||
- redpanda start
|
||||
- --smp 1
|
||||
- --overprovisioned
|
||||
- --node-id 0
|
||||
- --kafka-addr PLAINTEXT://0.0.0.0:29092,OUTSIDE://0.0.0.0:9092
|
||||
- --advertise-kafka-addr PLAINTEXT://redpanda:29092,OUTSIDE://redpanda:9092
|
||||
- --pandaproxy-addr 0.0.0.0:8082
|
||||
- --advertise-pandaproxy-addr localhost:8082
|
||||
ports:
|
||||
- 8081:8081
|
||||
- 8082:8082
|
||||
- 9092:9092
|
||||
- 9644:9644
|
||||
- 29092:29092
|
||||
volumes:
|
||||
- ./kafka:/app
|
||||
etl:
|
||||
image: etl-kafka
|
||||
platform: wasi/wasm
|
||||
build:
|
||||
context: etl
|
||||
environment:
|
||||
DATABASE_URL: mysql://root:whalehello@db:3306/mysql
|
||||
KAFKA_URL: kafka://redpanda:9092/order
|
||||
RUST_BACKTRACE: full
|
||||
RUST_LOG: info
|
||||
restart: unless-stopped
|
||||
runtime: io.containerd.wasmedge.v1
|
||||
db:
|
||||
image: mariadb:10.9
|
||||
environment:
|
||||
MYSQL_ROOT_PASSWORD: whalehello
|
1
wasmedge-kafka-mysql/db/db-password.txt
Normal file
1
wasmedge-kafka-mysql/db/db-password.txt
Normal file
|
@ -0,0 +1 @@
|
|||
whalehello
|
17
wasmedge-kafka-mysql/etl/Cargo.toml
Normal file
17
wasmedge-kafka-mysql/etl/Cargo.toml
Normal file
|
@ -0,0 +1,17 @@
|
|||
[package]
|
||||
name = "kafka"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
anyhow = "1.0.65"
|
||||
mega_etl = {git = "https://github.com/second-state/MEGA.git"}
|
||||
tokio_wasi = {version = '1.21', features = ["rt", "macros"]}
|
||||
env_logger = "0.9"
|
||||
log = "0.4"
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
serde_json = "1.0"
|
||||
http_req_wasi = "0.10"
|
||||
lazy_static = "1.4.0"
|
27
wasmedge-kafka-mysql/etl/Dockerfile
Normal file
27
wasmedge-kafka-mysql/etl/Dockerfile
Normal file
|
@ -0,0 +1,27 @@
|
|||
# syntax=docker/dockerfile:1
|
||||
FROM --platform=$BUILDPLATFORM rust:1.64 AS buildbase
|
||||
RUN <<EOT bash
|
||||
set -ex
|
||||
apt-get update
|
||||
apt-get install -y \
|
||||
git \
|
||||
clang
|
||||
rustup target add wasm32-wasi
|
||||
EOT
|
||||
# This line installs WasmEdge including the AOT compiler
|
||||
RUN curl -sSf https://raw.githubusercontent.com/WasmEdge/WasmEdge/master/utils/install.sh | bash
|
||||
|
||||
FROM buildbase AS build
|
||||
COPY Cargo.toml .
|
||||
COPY src ./src
|
||||
# Build the Wasm binary
|
||||
RUN --mount=type=cache,target=/usr/local/cargo/git/db \
|
||||
--mount=type=cache,target=/usr/local/cargo/registry/cache \
|
||||
--mount=type=cache,target=/usr/local/cargo/registry/index \
|
||||
cargo build --target wasm32-wasi --release
|
||||
# This line builds the AOT Wasm binary
|
||||
RUN /root/.wasmedge/bin/wasmedgec target/wasm32-wasi/release/kafka.wasm kafka.wasm
|
||||
|
||||
FROM scratch
|
||||
ENTRYPOINT [ "kafka.wasm" ]
|
||||
COPY --link --from=build /kafka.wasm /kafka.wasm
|
58
wasmedge-kafka-mysql/etl/src/main.rs
Normal file
58
wasmedge-kafka-mysql/etl/src/main.rs
Normal file
|
@ -0,0 +1,58 @@
|
|||
use mega_etl::{async_trait, Pipe, Transformer, TransformerError, TransformerResult};
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
struct Order {
|
||||
order_id: i32,
|
||||
product_id: i32,
|
||||
quantity: i32,
|
||||
amount: f32,
|
||||
shipping: f32,
|
||||
tax: f32,
|
||||
shipping_address: String,
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl Transformer for Order {
|
||||
async fn transform(inbound_data: &Vec<u8>) -> TransformerResult<Vec<String>> {
|
||||
let s = std::str::from_utf8(&inbound_data)
|
||||
.map_err(|e| TransformerError::Custom(e.to_string()))?;
|
||||
let order: Order = serde_json::from_str(String::from(s).as_str())
|
||||
.map_err(|e| TransformerError::Custom(e.to_string()))?;
|
||||
log::info!("{:?}", &order);
|
||||
let mut ret = vec![];
|
||||
let sql_string = format!(
|
||||
r"INSERT INTO orders VALUES ({:?}, {:?}, {:?}, {:?}, {:?}, {:?}, {:?}, CURRENT_TIMESTAMP);",
|
||||
order.order_id,
|
||||
order.product_id,
|
||||
order.quantity,
|
||||
order.amount,
|
||||
order.shipping,
|
||||
order.tax,
|
||||
order.shipping_address,
|
||||
);
|
||||
dbg!(sql_string.clone());
|
||||
ret.push(sql_string);
|
||||
Ok(ret)
|
||||
}
|
||||
|
||||
async fn init() -> TransformerResult<String> {
|
||||
Ok(String::from(
|
||||
r"CREATE TABLE IF NOT EXISTS orders (order_id INT, product_id INT, quantity INT, amount FLOAT, shipping FLOAT, tax FLOAT, shipping_address VARCHAR(50), date_registered TIMESTAMP DEFAULT CURRENT_TIMESTAMP);",
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
#[tokio::main(flavor = "current_thread")]
|
||||
async fn main() -> anyhow::Result<()> {
|
||||
env_logger::init();
|
||||
|
||||
// can use builder later
|
||||
let database_uri = std::env::var("DATABASE_URL")?;
|
||||
let kafka_uri = std::env::var("KAFKA_URL")?;
|
||||
let mut pipe = Pipe::new(database_uri, kafka_uri).await;
|
||||
|
||||
// This is async because this calls the async transform() function in Order
|
||||
pipe.start::<Order>().await?;
|
||||
Ok(())
|
||||
}
|
1
wasmedge-kafka-mysql/kafka/order.json
Normal file
1
wasmedge-kafka-mysql/kafka/order.json
Normal file
|
@ -0,0 +1 @@
|
|||
{"order_id": 1,"product_id": 12,"quantity": 2,"amount": 56.0,"shipping": 15.0,"tax": 2.0,"shipping_address": "Mataderos 2312"}
|
118
wasmedge-mysql-nginx/README.md
Normal file
118
wasmedge-mysql-nginx/README.md
Normal file
|
@ -0,0 +1,118 @@
|
|||
# Compose sample application
|
||||
|
||||

|
||||
|
||||
This sample demonstrates a web application with a WebAssembly (Wasm) microservice, written in Rust. The Wasm microservice is an HTTP API connected to a MySQL (MariaDB) database. The API is invoked via from JavaScript in a web interface serving static HTML. The microservice is compiled into WebAssembly (Wasm) and runs in the WasmEdge Runtime, a secure and lightweight alternative to natively compiled Rust apps in Linux containers. Checkout [this article](https://blog.logrocket.com/rust-microservices-server-side-webassembly/) or [this video](https://www.youtube.com/watch?v=VSqMPFr7SEs) to learn how the Rust code in this microservice works.
|
||||
|
||||
## WasmEdge server with Nginx proxy and MySQL database
|
||||
|
||||
Project structure:
|
||||
|
||||
```
|
||||
.
|
||||
+-- compose.yml
|
||||
|-- backend
|
||||
+-- Dockerfile
|
||||
|-- Cargo.toml
|
||||
|-- src
|
||||
+-- main.rs
|
||||
|-- frontend
|
||||
+-- index.html
|
||||
|-- js
|
||||
+-- app.js
|
||||
|-- db
|
||||
+-- orders.json
|
||||
|-- update_order.json
|
||||
```
|
||||
|
||||
The [compose.yml](compose.yml) file:
|
||||
|
||||
```yaml
|
||||
services:
|
||||
frontend:
|
||||
image: nginx:alpine
|
||||
ports:
|
||||
- 8090:80
|
||||
volumes:
|
||||
- ./frontend:/usr/share/nginx/html
|
||||
|
||||
backend:
|
||||
image: demo-microservice
|
||||
build:
|
||||
context: backend/
|
||||
platforms:
|
||||
- wasi/wasm32
|
||||
ports:
|
||||
- 8080:8080
|
||||
environment:
|
||||
DATABASE_URL: mysql://root:whalehello@db:3306/mysql
|
||||
RUST_BACKTRACE: full
|
||||
restart: unless-stopped
|
||||
runtime: io.containerd.wasmedge.v1
|
||||
|
||||
db:
|
||||
image: mariadb:10.9
|
||||
environment:
|
||||
MYSQL_ROOT_PASSWORD: whalehello
|
||||
```
|
||||
|
||||
The compose file defines an application with three services `frontend`, `backend` and `db`. The `frontend` is a simple Nginx server that hosts static web pages that access the `backend` web service, in the WasmEdge container, via HTTP port 8080. When deploying the application, docker compose maps port 8090 of the `frontend` service container to port 8090 of the host as specified in the file. Make sure that ports 8090 and 8080 on the host are not already being used.
|
||||
|
||||
## Deploy with docker compose
|
||||
|
||||
```bash
|
||||
$ docker compose up -d
|
||||
...
|
||||
⠿ Network wasmedge-mysql-nginx_default Created
|
||||
⠿ Container wasmedge-mysql-nginx-db-1 Created
|
||||
⠿ Container wasmedge-mysql-nginx-frontend-1 Created
|
||||
⠿ Container wasmedge-mysql-nginx-backend-1 Created
|
||||
```
|
||||
|
||||
## Expected result
|
||||
|
||||
```bash
|
||||
$ docker compose ps
|
||||
NAME COMMAND SERVICE STATUS PORTS
|
||||
wasmedge-mysql-nginx-backend-1 "order_demo_service.…" backend running 0.0.0.0:8080->8080/tcp, :::8080->8080/tcp
|
||||
wasmedge-mysql-nginx-db-1 "docker-entrypoint.s…" db running 3306/tcp
|
||||
wasmedge-mysql-nginx-frontend-1 "/docker-entrypoint.…" frontend running 0.0.0.0:8090->80/tcp, :::8090->80/tcp
|
||||
```
|
||||
|
||||
After the application starts, go to `http://localhost:8090` in your web browser to display the web frontend.
|
||||
|
||||
### Using the API with `curl`
|
||||
|
||||
As an alternative to the web frontend, you can use `curl` to interact with the WasmEdge API directly (the `backend` service).
|
||||
|
||||
When the WasmEdge web service receives a GET request to the `/init` endpoint, it would initialize the database with the `orders` table.
|
||||
|
||||
```bash
|
||||
curl http://localhost:8080/init
|
||||
```
|
||||
|
||||
When the WasmEdge web service receives a POST request to the `/create_order` endpoint, it extracts the JSON data from the POST body and inserts an `Order` record into the database table.
|
||||
To insert multiple records, use the `/create_orders` endpoint and POST a JSON array of `Order` objects:
|
||||
|
||||
```bash
|
||||
curl http://localhost:8080/create_orders -X POST -d @db/orders.json
|
||||
```
|
||||
|
||||
When the WasmEdge web service receives a GET request to the `/orders` endpoint, it gets all rows from the `orders` table and return the result set in a JSON array in the HTTP response.
|
||||
|
||||
```bash
|
||||
curl http://localhost:8080/orders
|
||||
```
|
||||
|
||||
When the WasmEdge web service receives a POST request to the `/update_order` endpoint, it extracts the JSON data from the POST body and update the `Order` record in the database table that matches the `order_id` in the input data.
|
||||
|
||||
```bash
|
||||
curl http://localhost:8080/update_order -X POST -d @db/update_order.json
|
||||
```
|
||||
|
||||
When the WasmEdge web service receives a GET request to the `/delete_order` endpoint, it deletes the row in the `orders` table that matches the `id` GET parameter.
|
||||
|
||||
```bash
|
||||
curl http://localhost:8080/delete_order?id=2
|
||||
```
|
||||
|
13
wasmedge-mysql-nginx/backend/Cargo.toml
Normal file
13
wasmedge-mysql-nginx/backend/Cargo.toml
Normal file
|
@ -0,0 +1,13 @@
|
|||
[package]
|
||||
name = "order_demo_service"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
anyhow = "1.0"
|
||||
serde_json = "1.0"
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
url = "2.3"
|
||||
mysql_async_wasi = "0.30"
|
||||
hyper_wasi = { version = "0.15", features = ["full"] }
|
||||
tokio_wasi = { version = "1", features = ["io-util", "fs", "net", "time", "rt", "macros"] }
|
29
wasmedge-mysql-nginx/backend/Dockerfile
Normal file
29
wasmedge-mysql-nginx/backend/Dockerfile
Normal file
|
@ -0,0 +1,29 @@
|
|||
# syntax=docker/dockerfile:1
|
||||
|
||||
FROM --platform=$BUILDPLATFORM rust:1.64 AS buildbase
|
||||
WORKDIR /src
|
||||
RUN <<EOT bash
|
||||
set -ex
|
||||
apt-get update
|
||||
apt-get install -y \
|
||||
git \
|
||||
clang
|
||||
rustup target add wasm32-wasi
|
||||
EOT
|
||||
# This line installs WasmEdge including the AOT compiler
|
||||
RUN curl -sSf https://raw.githubusercontent.com/WasmEdge/WasmEdge/master/utils/install.sh | bash
|
||||
|
||||
FROM buildbase AS build
|
||||
COPY Cargo.toml .
|
||||
COPY src ./src
|
||||
# Build the Wasm binary
|
||||
RUN --mount=type=cache,target=/usr/local/cargo/git/db \
|
||||
--mount=type=cache,target=/usr/local/cargo/registry/cache \
|
||||
--mount=type=cache,target=/usr/local/cargo/registry/index \
|
||||
cargo build --target wasm32-wasi --release
|
||||
# This line builds the AOT Wasm binary
|
||||
RUN /root/.wasmedge/bin/wasmedgec target/wasm32-wasi/release/order_demo_service.wasm order_demo_service.wasm
|
||||
|
||||
FROM scratch
|
||||
ENTRYPOINT [ "order_demo_service.wasm" ]
|
||||
COPY --link --from=build /src/order_demo_service.wasm /order_demo_service.wasm
|
237
wasmedge-mysql-nginx/backend/src/main.rs
Normal file
237
wasmedge-mysql-nginx/backend/src/main.rs
Normal file
|
@ -0,0 +1,237 @@
|
|||
use hyper::service::{make_service_fn, service_fn};
|
||||
use hyper::{Body, Method, Request, Response, StatusCode, Server};
|
||||
pub use mysql_async::prelude::*;
|
||||
pub use mysql_async::*;
|
||||
use std::convert::Infallible;
|
||||
use std::net::SocketAddr;
|
||||
use std::result::Result;
|
||||
use std::collections::HashMap;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
fn get_url() -> String {
|
||||
if let Ok(url) = std::env::var("DATABASE_URL") {
|
||||
let opts = Opts::from_url(&url).expect("DATABASE_URL invalid");
|
||||
if opts
|
||||
.db_name()
|
||||
.expect("a database name is required")
|
||||
.is_empty()
|
||||
{
|
||||
panic!("database name is empty");
|
||||
}
|
||||
url
|
||||
} else {
|
||||
"mysql://root:pass@127.0.0.1:3306/mysql".into()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
struct Order {
|
||||
order_id: i32,
|
||||
product_id: i32,
|
||||
quantity: i32,
|
||||
amount: f32,
|
||||
shipping: f32,
|
||||
tax: f32,
|
||||
shipping_address: String,
|
||||
}
|
||||
|
||||
impl Order {
|
||||
fn new(
|
||||
order_id: i32,
|
||||
product_id: i32,
|
||||
quantity: i32,
|
||||
amount: f32,
|
||||
shipping: f32,
|
||||
tax: f32,
|
||||
shipping_address: String,
|
||||
) -> Self {
|
||||
Self {
|
||||
order_id,
|
||||
product_id,
|
||||
quantity,
|
||||
amount,
|
||||
shipping,
|
||||
tax,
|
||||
shipping_address,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async fn handle_request(req: Request<Body>, pool: Pool) -> Result<Response<Body>, anyhow::Error> {
|
||||
match (req.method(), req.uri().path()) {
|
||||
(&Method::GET, "/") => Ok(Response::new(Body::from(
|
||||
"The valid endpoints are /init /create_order /create_orders /update_order /orders /delete_order",
|
||||
))),
|
||||
|
||||
// Simply echo the body back to the client.
|
||||
(&Method::POST, "/echo") => Ok(Response::new(req.into_body())),
|
||||
|
||||
// CORS OPTIONS
|
||||
(&Method::OPTIONS, "/init") => Ok(response_build(&String::from(""))),
|
||||
(&Method::OPTIONS, "/create_order") => Ok(response_build(&String::from(""))),
|
||||
(&Method::OPTIONS, "/create_orders") => Ok(response_build(&String::from(""))),
|
||||
(&Method::OPTIONS, "/update_order") => Ok(response_build(&String::from(""))),
|
||||
(&Method::OPTIONS, "/delete_order") => Ok(response_build(&String::from(""))),
|
||||
(&Method::OPTIONS, "/orders") => Ok(response_build(&String::from(""))),
|
||||
|
||||
(&Method::GET, "/init") => {
|
||||
let mut conn = pool.get_conn().await.unwrap();
|
||||
"DROP TABLE IF EXISTS orders;".ignore(&mut conn).await?;
|
||||
"CREATE TABLE orders (order_id INT, product_id INT, quantity INT, amount FLOAT, shipping FLOAT, tax FLOAT, shipping_address VARCHAR(20));".ignore(&mut conn).await?;
|
||||
drop(conn);
|
||||
Ok(response_build("{\"status\":true}"))
|
||||
}
|
||||
|
||||
(&Method::POST, "/create_order") => {
|
||||
let mut conn = pool.get_conn().await.unwrap();
|
||||
|
||||
let byte_stream = hyper::body::to_bytes(req).await?;
|
||||
let order: Order = serde_json::from_slice(&byte_stream).unwrap();
|
||||
|
||||
"INSERT INTO orders (order_id, product_id, quantity, amount, shipping, tax, shipping_address) VALUES (:order_id, :product_id, :quantity, :amount, :shipping, :tax, :shipping_address)"
|
||||
.with(params! {
|
||||
"order_id" => order.order_id,
|
||||
"product_id" => order.product_id,
|
||||
"quantity" => order.quantity,
|
||||
"amount" => order.amount,
|
||||
"shipping" => order.shipping,
|
||||
"tax" => order.tax,
|
||||
"shipping_address" => &order.shipping_address,
|
||||
})
|
||||
.ignore(&mut conn)
|
||||
.await?;
|
||||
|
||||
drop(conn);
|
||||
Ok(response_build("{\"status\":true}"))
|
||||
}
|
||||
|
||||
(&Method::POST, "/create_orders") => {
|
||||
let mut conn = pool.get_conn().await.unwrap();
|
||||
|
||||
let byte_stream = hyper::body::to_bytes(req).await?;
|
||||
let orders: Vec<Order> = serde_json::from_slice(&byte_stream).unwrap();
|
||||
|
||||
"INSERT INTO orders (order_id, product_id, quantity, amount, shipping, tax, shipping_address) VALUES (:order_id, :product_id, :quantity, :amount, :shipping, :tax, :shipping_address)"
|
||||
.with(orders.iter().map(|order| {
|
||||
params! {
|
||||
"order_id" => order.order_id,
|
||||
"product_id" => order.product_id,
|
||||
"quantity" => order.quantity,
|
||||
"amount" => order.amount,
|
||||
"shipping" => order.shipping,
|
||||
"tax" => order.tax,
|
||||
"shipping_address" => &order.shipping_address,
|
||||
}
|
||||
}))
|
||||
.batch(&mut conn)
|
||||
.await?;
|
||||
|
||||
drop(conn);
|
||||
Ok(response_build("{\"status\":true}"))
|
||||
}
|
||||
|
||||
(&Method::POST, "/update_order") => {
|
||||
let mut conn = pool.get_conn().await.unwrap();
|
||||
|
||||
let byte_stream = hyper::body::to_bytes(req).await?;
|
||||
let order: Order = serde_json::from_slice(&byte_stream).unwrap();
|
||||
|
||||
"UPDATE orders SET product_id=:product_id, quantity=:quantity, amount=:amount, shipping=:shipping, tax=:tax, shipping_address=:shipping_address WHERE order_id=:order_id"
|
||||
.with(params! {
|
||||
"product_id" => order.product_id,
|
||||
"quantity" => order.quantity,
|
||||
"amount" => order.amount,
|
||||
"shipping" => order.shipping,
|
||||
"tax" => order.tax,
|
||||
"shipping_address" => &order.shipping_address,
|
||||
"order_id" => order.order_id,
|
||||
})
|
||||
.ignore(&mut conn)
|
||||
.await?;
|
||||
|
||||
drop(conn);
|
||||
Ok(response_build("{\"status\":true}"))
|
||||
}
|
||||
|
||||
(&Method::GET, "/orders") => {
|
||||
let mut conn = pool.get_conn().await.unwrap();
|
||||
|
||||
let orders = "SELECT * FROM orders"
|
||||
.with(())
|
||||
.map(&mut conn, |(order_id, product_id, quantity, amount, shipping, tax, shipping_address)| {
|
||||
Order::new(
|
||||
order_id,
|
||||
product_id,
|
||||
quantity,
|
||||
amount,
|
||||
shipping,
|
||||
tax,
|
||||
shipping_address,
|
||||
)},
|
||||
).await?;
|
||||
|
||||
drop(conn);
|
||||
Ok(response_build(serde_json::to_string(&orders)?.as_str()))
|
||||
}
|
||||
|
||||
(&Method::GET, "/delete_order") => {
|
||||
let mut conn = pool.get_conn().await.unwrap();
|
||||
|
||||
let params: HashMap<String, String> = req.uri().query().map(|v| {
|
||||
url::form_urlencoded::parse(v.as_bytes()).into_owned().collect()
|
||||
}).unwrap_or_else(HashMap::new);
|
||||
let order_id = params.get("id");
|
||||
|
||||
"DELETE FROM orders WHERE order_id=:order_id"
|
||||
.with(params! { "order_id" => order_id, })
|
||||
.ignore(&mut conn)
|
||||
.await?;
|
||||
|
||||
drop(conn);
|
||||
Ok(response_build("{\"status\":true}"))
|
||||
}
|
||||
|
||||
// Return the 404 Not Found for other routes.
|
||||
_ => {
|
||||
let mut not_found = Response::default();
|
||||
*not_found.status_mut() = StatusCode::NOT_FOUND;
|
||||
Ok(not_found)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// CORS headers
|
||||
fn response_build(body: &str) -> Response<Body> {
|
||||
Response::builder()
|
||||
.header("Access-Control-Allow-Origin", "*")
|
||||
.header("Access-Control-Allow-Methods", "GET, POST, OPTIONS")
|
||||
.header("Access-Control-Allow-Headers", "api,Keep-Alive,User-Agent,Content-Type")
|
||||
.body(Body::from(body.to_owned()))
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
#[tokio::main(flavor = "current_thread")]
|
||||
async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
|
||||
let opts = Opts::from_url(&*get_url()).unwrap();
|
||||
let builder = OptsBuilder::from_opts(opts);
|
||||
// The connection pool will have a min of 5 and max of 10 connections.
|
||||
let constraints = PoolConstraints::new(5, 10).unwrap();
|
||||
let pool_opts = PoolOpts::default().with_constraints(constraints);
|
||||
let pool = Pool::new(builder.pool_opts(pool_opts));
|
||||
|
||||
let addr = SocketAddr::from(([0, 0, 0, 0], 8080));
|
||||
let make_svc = make_service_fn(|_| {
|
||||
let pool = pool.clone();
|
||||
async move {
|
||||
Ok::<_, Infallible>(service_fn(move |req| {
|
||||
let pool = pool.clone();
|
||||
handle_request(req, pool)
|
||||
}))
|
||||
}
|
||||
});
|
||||
let server = Server::bind(&addr).serve(make_svc);
|
||||
if let Err(e) = server.await {
|
||||
eprintln!("server error: {}", e);
|
||||
}
|
||||
Ok(())
|
||||
}
|
25
wasmedge-mysql-nginx/compose.yml
Normal file
25
wasmedge-mysql-nginx/compose.yml
Normal file
|
@ -0,0 +1,25 @@
|
|||
services:
|
||||
frontend:
|
||||
image: nginx:alpine
|
||||
ports:
|
||||
- 8090:80
|
||||
volumes:
|
||||
- ./frontend:/usr/share/nginx/html
|
||||
|
||||
backend:
|
||||
image: demo-microservice
|
||||
platform: wasi/wasm
|
||||
build:
|
||||
context: backend/
|
||||
ports:
|
||||
- 8080:8080
|
||||
environment:
|
||||
DATABASE_URL: mysql://root:whalehello@db:3306/mysql
|
||||
RUST_BACKTRACE: full
|
||||
restart: unless-stopped
|
||||
runtime: io.containerd.wasmedge.v1
|
||||
|
||||
db:
|
||||
image: mariadb:10.9
|
||||
environment:
|
||||
MYSQL_ROOT_PASSWORD: whalehello
|
47
wasmedge-mysql-nginx/db/orders.json
Normal file
47
wasmedge-mysql-nginx/db/orders.json
Normal file
|
@ -0,0 +1,47 @@
|
|||
[
|
||||
{
|
||||
"order_id": 1,
|
||||
"product_id": 12,
|
||||
"quantity": 2,
|
||||
"amount": 56.0,
|
||||
"shipping": 15.0,
|
||||
"tax": 2.0,
|
||||
"shipping_address": "Mataderos 2312"
|
||||
},
|
||||
{
|
||||
"order_id": 2,
|
||||
"product_id": 15,
|
||||
"quantity": 3,
|
||||
"amount": 256.0,
|
||||
"shipping": 30.0,
|
||||
"tax": 16.0,
|
||||
"shipping_address": "1234 NW Bobcat"
|
||||
},
|
||||
{
|
||||
"order_id": 3,
|
||||
"product_id": 11,
|
||||
"quantity": 5,
|
||||
"amount": 536.0,
|
||||
"shipping": 50.0,
|
||||
"tax": 24.0,
|
||||
"shipping_address": "20 Havelock"
|
||||
},
|
||||
{
|
||||
"order_id": 4,
|
||||
"product_id": 8,
|
||||
"quantity": 8,
|
||||
"amount": 126.0,
|
||||
"shipping": 20.0,
|
||||
"tax": 12.0,
|
||||
"shipping_address": "224 Pandan Loop"
|
||||
},
|
||||
{
|
||||
"order_id": 5,
|
||||
"product_id": 24,
|
||||
"quantity": 1,
|
||||
"amount": 46.0,
|
||||
"shipping": 10.0,
|
||||
"tax": 2.0,
|
||||
"shipping_address": "No.10 Jalan Besar"
|
||||
}
|
||||
]
|
9
wasmedge-mysql-nginx/db/update_order.json
Normal file
9
wasmedge-mysql-nginx/db/update_order.json
Normal file
|
@ -0,0 +1,9 @@
|
|||
{
|
||||
"order_id": 3,
|
||||
"product_id": 12,
|
||||
"quantity": 2,
|
||||
"amount": 56.0,
|
||||
"shipping": 15.0,
|
||||
"tax": 2.0,
|
||||
"shipping_address": "123 Main Street"
|
||||
}
|
102
wasmedge-mysql-nginx/frontend/index.html
Normal file
102
wasmedge-mysql-nginx/frontend/index.html
Normal file
|
@ -0,0 +1,102 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Demo App</title>
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-Zenh87qX5JnK2Jl0vWa8Ck2rdkQ2Bzep5IDxbcnCeuOxjzrPF/et3URy9Bv1WTRi" crossorigin="anonymous" />
|
||||
<style>.d-none { display: none; }</style>
|
||||
</head>
|
||||
<body class="mb-5">
|
||||
<div class="container mt-5">
|
||||
<div id="app-loading-display">
|
||||
<h1>Loading...</h1>
|
||||
</div>
|
||||
|
||||
<div id="order-display" class="d-none">
|
||||
<h1>Welcome to the Demo!</h1>
|
||||
<p>This application is served using nginx for the website, Wasm for the backend, and MariaDB for the database.</p>
|
||||
|
||||
<div id="order-empty-text" class="d-none">
|
||||
<em>There are currently no orders to display!</em>
|
||||
</div>
|
||||
|
||||
<table id="order-table" class="d-none table table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Id</th>
|
||||
<th>Product Id</th>
|
||||
<th>Quantity</th>
|
||||
<th>Amount</th>
|
||||
<th>Shipping</th>
|
||||
<th>Tax</th>
|
||||
<th>Address</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody></tbody>
|
||||
</table>
|
||||
|
||||
<hr />
|
||||
|
||||
<div id="add-order-wrapper" class="d-none row">
|
||||
<div class="col-6">
|
||||
<div class="accordion" id="accordionExample">
|
||||
<div class="accordion-item">
|
||||
<h2 class="accordion-header" id="addOrderHeading">
|
||||
<button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#addOrder" aria-controls="addOrder">
|
||||
Add an order
|
||||
</button>
|
||||
</h2>
|
||||
|
||||
<div id="addOrder" class="accordion-collapse collapse p-3" aria-labelledby="addOrderHeading" data-bs-parent="#accordionExample">
|
||||
<form id="add-order-form">
|
||||
<div class="mb-3">
|
||||
<label for="order-id" class="form-label">Order Id</label>
|
||||
<input type="number" required class="form-control" id="order-id" aria-describedby="orderIdHelp">
|
||||
<div id="orderIdHelp" class="form-text">The ID of the order</div>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="product-id" class="form-label">Product Id</label>
|
||||
<input type="number" required class="form-control" id="product-id" aria-describedby="productIdHelp">
|
||||
<div id="productIdHelp" class="form-text">The ID of the product</div>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="quantity" class="form-label">Quantity</label>
|
||||
<input type="number" required class="form-control" id="quantity" aria-describedby="quantityHelp">
|
||||
<div id="quantityHelp" class="form-text">How many of the product?</div>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="amount" class="form-label">Amount</label>
|
||||
<input type="number" required class="form-control" id="amount" aria-describedby="amountHelp">
|
||||
<div id="amountHelp" class="form-text">The total amount</div>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="tax" class="form-label">Tax</label>
|
||||
<input type="number" required class="form-control" id="tax" aria-describedby="taxHelp">
|
||||
<div id="taxHelp" class="form-text">The total amount of tax</div>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="shippingAmount" class="form-label">Shipping Amount</label>
|
||||
<input type="number" required class="form-control" id="shippingAmount" aria-describedby="shippingAmountHelp">
|
||||
<div id="shippingAmountHelp" class="form-text">The total amount for shipping</div>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="shippingAddress" class="form-label">Shipping Address</label>
|
||||
<input type="text" required class="form-control" id="shippingAddress" aria-describedby="addressHelp">
|
||||
<div id="addressHelp" class="form-text">Where to send the order</div>
|
||||
</div>
|
||||
|
||||
<input type="submit" class="btn btn-success" value="Add Order" />
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-OERcA2EqjJCMA+/3y+gxIOqMEjwtxJY7qPCqsdltbNJuaOe923+mo//f6V8Qbsw3" crossorigin="anonymous"></script>
|
||||
<script type="text/javascript" src="/js/app.js"></script>
|
||||
</body>
|
||||
</html>
|
135
wasmedge-mysql-nginx/frontend/js/app.js
Normal file
135
wasmedge-mysql-nginx/frontend/js/app.js
Normal file
|
@ -0,0 +1,135 @@
|
|||
(function() {
|
||||
let orders = null;
|
||||
const appLoadingEle = document.getElementById("app-loading-display");
|
||||
const orderWrapperEle = document.getElementById("order-display");
|
||||
const orderEmptyTextEle = document.getElementById("order-empty-text");
|
||||
const orderTableEle = document.getElementById("order-table");
|
||||
const orderTableBodyEle = document.querySelector("#order-table tbody");
|
||||
const addOrderEle = document.getElementById("add-order-wrapper");
|
||||
const addOrderForm = document.getElementById("add-order-form");
|
||||
|
||||
const orderIdField = document.getElementById("order-id");
|
||||
const productIdField = document.getElementById("product-id");
|
||||
const quantityField = document.getElementById("quantity");
|
||||
const amountField = document.getElementById("amount");
|
||||
const taxField = document.getElementById("tax");
|
||||
const shippingField = document.getElementById("shippingAmount");
|
||||
const shippingAddressField = document.getElementById("shippingAddress");
|
||||
|
||||
function fetchOrders() {
|
||||
fetch("http://localhost:8080/orders")
|
||||
.then(r => r.json())
|
||||
.then(r => orders = r)
|
||||
.then(renderOrders)
|
||||
.catch((e) => {
|
||||
init();
|
||||
});
|
||||
}
|
||||
|
||||
function init() {
|
||||
fetch("http://localhost:8080/init")
|
||||
.then(() => fetchOrders())
|
||||
.catch((e) => displayError(e));
|
||||
}
|
||||
|
||||
function renderOrders() {
|
||||
appLoadingEle.classList.add("d-none");
|
||||
orderWrapperEle.classList.remove("d-none");
|
||||
addOrderEle.classList.remove("d-none");
|
||||
|
||||
if (orders.length === 0) {
|
||||
orderEmptyTextEle.classList.remove("d-none");
|
||||
orderTableEle.classList.add("d-none");
|
||||
return;
|
||||
}
|
||||
|
||||
orderEmptyTextEle.classList.add("d-none");
|
||||
orderTableEle.classList.remove("d-none");
|
||||
|
||||
while (orderTableBodyEle.firstChild) {
|
||||
orderTableBodyEle.removeChild(orderTableBodyEle.firstChild);
|
||||
}
|
||||
|
||||
orders.forEach((order) => {
|
||||
const orderId = order.order_id;
|
||||
|
||||
const row = document.createElement("tr");
|
||||
|
||||
row.appendChild(createCell(order.order_id));
|
||||
row.appendChild(createCell(order.product_id));
|
||||
row.appendChild(createCell(order.quantity));
|
||||
row.appendChild(createCell(order.amount));
|
||||
row.appendChild(createCell(order.shipping));
|
||||
row.appendChild(createCell(order.tax));
|
||||
row.appendChild(createCell(order.shipping_address));
|
||||
|
||||
const actionCell = document.createElement("td");
|
||||
|
||||
const deleteButton = document.createElement("button");
|
||||
deleteButton.classList.add(...["btn","btn-sm","btn-danger"]);
|
||||
deleteButton.innerText = "Delete";
|
||||
|
||||
deleteButton.addEventListener("click", (e) => {
|
||||
e.preventDefault();
|
||||
deleteOrder(orderId);
|
||||
});
|
||||
|
||||
actionCell.appendChild(deleteButton);
|
||||
|
||||
row.appendChild(actionCell);
|
||||
|
||||
orderTableBodyEle.appendChild(row);
|
||||
});
|
||||
}
|
||||
|
||||
function createCell(contents) {
|
||||
const cell = document.createElement("td");
|
||||
cell.innerText = contents;
|
||||
return cell;
|
||||
}
|
||||
|
||||
function deleteOrder(orderId) {
|
||||
fetch(`http://localhost:8080/delete_order?id=${orderId}`)
|
||||
.then(() => fetchOrders());
|
||||
}
|
||||
|
||||
function displayError(err) {
|
||||
alert("Error:" + err);
|
||||
}
|
||||
|
||||
function onAddFormSubmit(e) {
|
||||
e.preventDefault();
|
||||
|
||||
const data = {
|
||||
order_id : parseFloat(orderIdField.value),
|
||||
product_id : parseFloat(productIdField.value),
|
||||
quantity : parseFloat(quantityField.value),
|
||||
amount : parseFloat(amountField.value),
|
||||
shipping : parseFloat(shippingField.value),
|
||||
tax : parseFloat(taxField.value),
|
||||
shipping_address : shippingAddressField.value,
|
||||
};
|
||||
|
||||
fetch("http://localhost:8080/create_order", {
|
||||
method: "POST",
|
||||
body: JSON.stringify(data),
|
||||
headers: { "Content-type": "application/json" },
|
||||
}).then(() => fetchOrders())
|
||||
.then(() => resetAddOrderForm());
|
||||
|
||||
alert("Order added");
|
||||
}
|
||||
|
||||
function resetAddOrderForm() {
|
||||
orderIdField.value = "";
|
||||
productIdField.value = "";
|
||||
quantityField.value = "";
|
||||
amountField.value = "";
|
||||
shippingField.value = "";
|
||||
taxField.value = "";
|
||||
shippingAddressField.value = "";
|
||||
}
|
||||
|
||||
fetchOrders();
|
||||
addOrderForm.addEventListener("submit", onAddFormSubmit);
|
||||
})();
|
Loading…
Add table
Add a link
Reference in a new issue