Docker Compose 用于 Java 后端和 Python 前端应用程序。

huangapple go评论70阅读模式
英文:

Docker compose for java backend and python frontend application

问题

以下是翻译好的内容:

我有一个简单的Spring Boot Java后端应用程序,可以从列表中获取元素(端点/get/{id})并将元素添加到列表中(端点/add/{product}):

@RestController
public class DemoController {

    List<String> products = Arrays.asList("test");

    @PostMapping(path="/add/{product}")
    public int addProduct(@PathVariable final String product){
        products.add(product);
        return products.size()-1;
    }

    @GetMapping(path="/get/{id}")
    public String getValue(@PathVariable final int id){
        return products.get(id);
    }
}

我为此创建了Dockerfile,如下所示:

FROM openjdk:11

# 将打包的jar文件复制到我们的Docker镜像中
COPY target/demo-0.0.1-SNAPSHOT.jar /demo.jar

EXPOSE 8080/tcp

# 设置启动命令以执行jar文件
CMD ["java", "-jar", "/demo.jar"]

现在我可以构建镜像(docker build -t java_backend .)并运行应用程序(docker run --rm -p 8080:8080 java_backend)。

因此,在localhost:8080/get/0下,我得到了"test",在localhost:8080/add/something下,我可以添加元素。一切正常。

作为前端,我有一个简单的Python应用程序,如下所示:

from flask import Flask, request
import requests as r
import os
app = Flask(__name__)

@app.route("/")
def renderProduct():
    return """
            <html>
                <head>
                    <title>""" + os.environ["title"] + """</title>
                </head>    
                <form id="1" method="POST">
                    <input name="getID"/>
                    <br>
                    <input name="addID">
                    <input type="submit">
                </form>
                </html>
                """

@app.route("/", methods=["POST"])
def queryAndRender():
    builded = "<html>"
    if request.form["getID"] is not None:
        resp = r.get("http://localhost:8080/get/" + request.form["getID"])
        builded = builded + "PRODUCT:" + resp.text + "<br>"

    if request.form["addID"] is not None:
        resp = r.get("http://localhost:8080/add/" + request.form["addID"])
        builded = builded + "ADDED ID:" + resp.text + "<br>"

    builded = builded + """<html>
                            <head>
                                <title>""" + os.environ["title"] + """</title>
                            </head>
                            <form id="1" method="POST">
                                <input name="getID"/>
                                <br>
                                <input name="addID">
                                <input type="submit">
                            </form>
                            </html>
                            """
    return builded;


if __name__ == "__main__":
    app.run()

Dockerfile如下:

ARG version=3.8.5-alpine3.11
FROM python:${version}

ENV title="Hello world"
ENV test testspacja
ENV FLASK_APP=/main.py

RUN pip install Flask==1.1.2
RUN pip install requests==2.22.0

COPY main.py /
RUN sed -i 's/localhost:8080/backend/g' /main.py

EXPOSE 80/tcp

ENTRYPOINT ["flask", "run"]
CMD ["-h", "0.0.0.0", "-p", "80"]

最后,我创建了docker-compose.yml文件来运行它们两个:

version: '3.3'
services:
    backend:
        image: java_backend
        ports:
             - "8080:8080"

    frontend:
        image: frontend
        ports:
            - "8081:80"

现在我尝试启动docker-compose up --build backend frontend

前端和后端是独立工作的,因此如果我尝试在localhost:8080/get/0中放置localhost:8080/get/0,我会得到"test",如果我转到localhost:8081,我会看到我的前端。但是,如果我在文本框中输入一些值并单击提交,我会收到500 Internal Server Error。因此,服务之间没有连接。您能告诉我为什么吗?

英文:

I have simple spring boot java backend application which get element from the list (endpoint /get/{id}) and add element to the list (endpoint /add/{product}):

@RestController
public class DemoController {

    List&lt;String&gt; products = Arrays.asList(&quot;test&quot;);

    @PostMapping(path=&quot;/add/{product}&quot;)
    public int addProduct(@PathVariable final String product){
        products.add(product);
        return products.size()-1;
    }

    @GetMapping(path=&quot;/get/{id}&quot;)
    public String getValue(@PathVariable final int id){
        return products.get(id);
    }
}

I created Dockerfile for this like:

FROM openjdk:11

# copy the packaged jar file into our docker image
COPY target/demo-0.0.1-SNAPSHOT.jar /demo.jar

EXPOSE 8080/tcp

# set the startup command to execute the jar
CMD [&quot;java&quot;, &quot;-jar&quot;, &quot;/demo.jar&quot;]

Now I can build image (docker build -t java_backend .) and run application (docker run --rm -p 8080:8080 java_backend).

Thus, under localhost:8080/get/0 I got &quot;test&quot;, under localhost:8080/add/something I can add element. Everything is fine.

As frontend I have simple python application like:

from flask import Flask, request
import requests as r
import os
app = Flask(__name__)

@app.route(&quot;/&quot;)
def renderProduct():
    return &quot;&quot;&quot;
            &lt;html&gt;
                &lt;head&gt;
                    &lt;title&gt;&quot;&quot;&quot; + os.environ[&quot;title&quot;] + &quot;&quot;&quot;&lt;/title&gt;
                &lt;/head&gt;    
                &lt;form id=&quot;1&quot; method=&quot;POST&quot;&gt;
                    &lt;input name=&quot;getID&quot;/&gt;
                    &lt;br&gt;
                    &lt;input name=&quot;addID&quot;&gt;
                    &lt;input type=&quot;submit&quot;&gt;
                &lt;/form&gt;
                &lt;/html&gt;
                &quot;&quot;&quot;

@app.route(&quot;/&quot;, methods=[&quot;POST&quot;])
def queryAndRender():
    builded = &quot;&lt;html&gt;&quot;
    if request.form[&quot;getID&quot;] is not None:
        resp = r.get(&quot;http://localhost:8080/get/&quot; + request.form[&quot;getID&quot;])
        builded = builded + &quot;PRODUCT:&quot; + resp.text + &quot;&lt;br&gt;&quot;

    if request.form[&quot;addID&quot;] is not None:
        resp = r.get(&quot;http://localhost:8080/add/&quot; + request.form[&quot;addID&quot;])
        builded = builded + &quot;ADDED ID:&quot; + resp.text + &quot;&lt;br&gt;&quot;

    builded = builded + &quot;&quot;&quot;&lt;html&gt;
                            &lt;head&gt;
                                &lt;title&gt;&quot;&quot;&quot; + os.environ[&quot;title&quot;] + &quot;&quot;&quot;&lt;/title&gt;
                            &lt;/head&gt;
                            &lt;form id=&quot;1&quot; method=&quot;POST&quot;&gt;
                                &lt;input name=&quot;getID&quot;/&gt;
                                &lt;br&gt;
                                &lt;input name=&quot;addID&quot;&gt;
                                &lt;input type=&quot;submit&quot;&gt;
                            &lt;/form&gt;
                            &lt;/html&gt;
                            &quot;&quot;&quot;

    return builded;


if __name__ == &quot;__main__&quot;:
    app.run()

And Dockerfile:

ARG version=3.8.5-alpine3.11
FROM python:${version}

ENV title=&quot;Hello world&quot;
ENV test testspacja
ENV FLASK_APP=/main.py

RUN pip install Flask==1.1.2
RUN pip install requests==2.22.0

COPY main.py /
RUN sed -i &#39;s/localhost:8080/backend/g&#39; /main.py

EXPOSE 80/tcp

ENTRYPOINT [&quot;flask&quot;, &quot;run&quot;]
CMD [&quot;-h&quot;, &quot;0.0.0.0&quot;, &quot;-p&quot;, &quot;80&quot;]

At the end I created docker-compose.yml file to run both of them:

version: &#39;3.3&#39;
services:
        backend:
                image: java_backend
                ports:
                         - &quot;8080:8080&quot;

        frontend:
                image: frontend
                ports:
                        - &quot;8081:80&quot;

Now I try to start docker-compose up --build backend frontend.

Frontend and backend are working independent, hence if I try put localhost:8080/get/0 I am getting &quot;test&quot;, If I go to localhost:8081 I see my frontend. But if I put some values in textboxes and click submit then I got 500 Internal Server Error. So services are not connected. Could you please tell me why?

答案1

得分: 0

我认为你在意外地擦除了后端端口。尝试将以下内容替换为:

RUN sed -i &#39;s/localhost:8080/backend:8080/g&#39; /main.py
英文:

I think you are accidentally erasing the backend port. Try replacing

RUN sed -i &#39;s/localhost:8080/backend/g&#39; /main.py

with

RUN sed -i &#39;s/localhost:8080/backend:8080/g&#39; /main.py

答案2

得分: 0

我有一个额外的问题。假设我想从容器中启动前端,但只从我的本地IDE(IntelliJ)启动后端。

当然,RUN sed -i 's/localhost:8080/backend/g' /main.py 这一行被注释了,所以前端调用的是 http://localhost:8080 下的端点。

在这种情况下,前端位于 http://localhost:8081,后端位于 http://localhost:8080(两个端点 - /get/{id}/add/{product})。但为什么在容器中运行的前端无法“看到”我的后端呢?

英文:

I have one additional question for this. Let's suppose that I would like start frontend from container but backend only from the my local IDE (IntelliJ).

Of course line RUN sed -i &#39;s/localhost:8080/backend/g&#39; /main.py is commented so frontent is calling endpoints under http://localhost:8080.

In this case frontend is under http://localhost:8081 and backend under http://localhost:8080 (two endpoints - /get/{id} and /add/{product}). But why frontend which is running in container doesn't "see" my backend?

huangapple
  • 本文由 发表于 2020年9月20日 23:59:20
  • 转载请务必保留本文链接:https://go.coder-hub.com/63980939.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定