Merge branch 'docker:master' into feature/testcontainers

pull/491/head
Julian König 3 weeks ago committed by GitHub
commit 1ef170e10a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 52
      README.md
  2. 11
      angular/.docker/docker-compose.yaml
  3. 7
      angular/README.md
  4. 10
      apache-php/.docker/docker-compose.yaml
  5. 7
      apache-php/README.md
  6. 9
      django/.docker/docker-compose.yaml
  7. 7
      django/README.md
  8. 13
      fastapi/.docker/docker-compose.yaml
  9. 7
      fastapi/README.md
  10. 16
      flask-redis/.docker/docker-compose.yaml
  11. 7
      flask-redis/README.md
  12. 10
      flask/.docker/docker-compose.yaml
  13. 7
      flask/README.md
  14. 8
      icon_devenvs.svg
  15. 13
      icon_wasm.svg
  16. 38
      nginx-aspnet-mysql/.docker/docker-compose.yaml
  17. 9
      nginx-aspnet-mysql/README.md
  18. 27
      nginx-flask-mongo/.docker/docker-compose.yaml
  19. 7
      nginx-flask-mongo/README.md
  20. 61
      nginx-flask-mysql/.docker/docker-compose.yaml
  21. 7
      nginx-flask-mysql/README.md
  22. 50
      nginx-golang-mysql/.docker/docker-compose.yaml
  23. 9
      nginx-golang-mysql/README.md
  24. 50
      nginx-golang-postgres/.docker/docker-compose.yaml
  25. 9
      nginx-golang-postgres/README.md
  26. 19
      nginx-golang/.docker/docker-compose.yaml
  27. 7
      nginx-golang/README.md
  28. 43
      react-express-mongodb/.docker/docker-compose.yaml
  29. 7
      react-express-mongodb/README.md
  30. 8
      react-express-mongodb/compose.yaml
  31. 64
      react-express-mysql/.docker/docker-compose.yaml
  32. 7
      react-express-mysql/README.md
  33. 61
      react-java-mysql/.docker/docker-compose.yaml
  34. 7
      react-java-mysql/README.md
  35. 11
      react-nginx/.docker/docker-compose.yaml
  36. 7
      react-nginx/README.md
  37. 51
      react-rust-postgres/.docker/docker-compose.yaml
  38. 7
      react-rust-postgres/readme.md
  39. 32
      sparkjava-mysql/.docker/docker-compose.yaml
  40. 7
      sparkjava-mysql/README.md
  41. 9
      sparkjava/.docker/docker-compose.yaml
  42. 7
      sparkjava/README.md
  43. 34
      spring-postgres/.docker/docker-compose.yaml
  44. 7
      spring-postgres/README.md
  45. 22
      traefik-golang/.docker/docker-compose.yaml
  46. 7
      traefik-golang/README.md
  47. 9
      vuejs/.docker/docker-compose.yaml
  48. 7
      vuejs/README.md
  49. 110
      wasmedge-kafka-mysql/README.md
  50. 36
      wasmedge-kafka-mysql/compose.yml
  51. 1
      wasmedge-kafka-mysql/db/db-password.txt
  52. 17
      wasmedge-kafka-mysql/etl/Cargo.toml
  53. 27
      wasmedge-kafka-mysql/etl/Dockerfile
  54. 58
      wasmedge-kafka-mysql/etl/src/main.rs
  55. 1
      wasmedge-kafka-mysql/kafka/order.json
  56. 118
      wasmedge-mysql-nginx/README.md
  57. 13
      wasmedge-mysql-nginx/backend/Cargo.toml
  58. 29
      wasmedge-mysql-nginx/backend/Dockerfile
  59. 237
      wasmedge-mysql-nginx/backend/src/main.rs
  60. 25
      wasmedge-mysql-nginx/compose.yml
  61. 47
      wasmedge-mysql-nginx/db/orders.json
  62. 9
      wasmedge-mysql-nginx/db/update_order.json
  63. 102
      wasmedge-mysql-nginx/frontend/index.html
  64. 135
      wasmedge-mysql-nginx/frontend/js/app.js

@ -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.&nbsp;<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.&nbsp;<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.&nbsp;<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&nbsp;<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.&nbsp;<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.&nbsp;<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&nbsp;<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.&nbsp;<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.&nbsp;<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.&nbsp;<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.&nbsp;<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.&nbsp;<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.&nbsp;<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.&nbsp;<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.&nbsp;<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)&nbsp;<a href="angular"><img src="icon_devenvs.svg" alt="Use with Docker Dev Environments" height="30" align="top"/></a>
- [`Spark`](sparkjava)&nbsp;<a href="sparkjava"><img src="icon_devenvs.svg" alt="Use with Docker Dev Environments" height="30" align="top"/></a>
- [`VueJS`](vuejs)&nbsp;<a href="vuejs"><img src="icon_devenvs.svg" alt="Use with Docker Dev Environments" height="30" align="top"/></a>
- [`Flask`](flask)&nbsp;<a href="flask"><img src="icon_devenvs.svg" alt="Use with Docker Dev Environments" height="30" align="top"/></a>
- [`PHP`](apache-php)&nbsp;<a href="apache-php"><img src="icon_devenvs.svg" alt="Use with Docker Dev Environments" height="30" align="top"/></a>
- [`Traefik`](traefik-golang)&nbsp;<a href="traefik-golang"><img src="icon_devenvs.svg" alt="Use with Docker Dev Environments" height="30" align="top"/></a>
- [`Django`](django)&nbsp;<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)&nbsp;<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

@ -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:

@ -0,0 +1,110 @@
# Compose sample application
![Compatible with Docker+Wasm](../icon_wasm.svg)
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;
... ...
```

@ -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

@ -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"

@ -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

@ -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(())
}

@ -0,0 +1 @@
{"order_id": 1,"product_id": 12,"quantity": 2,"amount": 56.0,"shipping": 15.0,"tax": 2.0,"shipping_address": "Mataderos 2312"}

@ -0,0 +1,118 @@
# Compose sample application
![Compatible with Docker+Wasm](../icon_wasm.svg)
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
```

@ -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"] }

@ -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

@ -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(())
}

@ -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

@ -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"
}
]

@ -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"
}

@ -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>

@ -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…
Cancel
Save