slimtoolkit / slim

Slim(toolkit): Don't change anything in your container image and minify it by up to 30x (and for compiled languages even more) making it secure too! (free and open source)
Apache License 2.0
19.58k stars 736 forks source link

container start fail with sanic+sanic-openapi #106

Open lethe3000 opened 4 years ago

lethe3000 commented 4 years ago

I have a simple sanic server, it runs ok with normal docker, but failed to launch when slimed.

$ docker build -t server .
$ docker-slim build server .
$ docker run -d server.slim

and container exit with error

Traceback (most recent call last):
  File "main.py", line 12, in <module>
    app.blueprint(swagger_blueprint)
  File "/usr/local/lib/python3.7/site-packages/sanic/app.py", line 726, in blueprint
    blueprint.register(self, options)
  File "/usr/local/lib/python3.7/site-packages/sanic/blueprints.py", line 158, in register
    uri, future.file_or_directory, *future.args, **future.kwargs
  File "/usr/local/lib/python3.7/site-packages/sanic/app.py", line 704, in static
    content_type,
  File "/usr/local/lib/python3.7/site-packages/sanic/static.py", line 146, in register
    )(_handler)
  File "/usr/local/lib/python3.7/site-packages/sanic/app.py", line 201, in response
    name=name,
  File "/usr/local/lib/python3.7/site-packages/sanic/router.py", line 147, in add
    self._add(uri, methods, handler, host, name)
  File "/usr/local/lib/python3.7/site-packages/sanic/router.py", line 303, in _add
    route = merge_route(route, methods, handler)
  File "/usr/local/lib/python3.7/site-packages/sanic/router.py", line 255, in merge_route
    uri, ",".join(list(duplicated))
sanic.router.RouteExists: Route already registered: /swagger/<file_uri:/?.+> [HEAD,GET]

code as below, include main.py, Dockerfile and requirements.txt

Dockerfile

FROM python:3.7
COPY requirements.txt /requirements.txt
RUN pip install -r requirements.txt

COPY . /app
WORKDIR /app
EXPOSE 8000
CMD python main.py

main.py

from sanic import Sanic
from sanic_openapi import swagger_blueprint
app = Sanic()
app.blueprint(swagger_blueprint)
if __name__ == "__main__":
    app.run(host="0.0.0.0", port=8000)

requirements.txt

sanic
sanic-openapi

Note that if I commented out line app.blueprint(swagger_blueprint), slim container can launch success

kcq commented 4 years ago

@lethe3000 thank you for the code samples! it'll help with the repro! In the meantime, can you try something to see if it makes a difference... Do you mind specifying a custom http probe to hit the swagger endpoint that gets exposed with the swagger blueprint you have there? Your call should look something like this: docker-slim build --http-probe-cmd / --http-probe-cmd /swagger server

You can find more info about the HTTP probes here: https://github.com/docker-slim/docker-slim#http-probe-commands

P.S. I noticed you have a dot at the end of the docker-slim build command. What are your expectations/intentions there?

lethe3000 commented 4 years ago

I noticed you have a dot at the end of the docker-slim build command. What are your expectations/intentions there?

extra dot is a typo, please dismiss, I'm trying add http probe..

lethe3000 commented 4 years ago

I've modify main.py, added a simple router will return {"hello":"world"} when access /, and build slim and run. as a result, container now can launch success and access to / can get expected response. but access to /swagger/ page render failed because of static file 404 error.

main.py

from sanic import Sanic
from sanic_openapi import swagger_blueprint
from sanic.response import json

app = Sanic()
app.blueprint(swagger_blueprint)

@app.route("/")
async def test(request):
    return json({"hello": "world"})

if __name__ == "__main__":
    app.run(host="0.0.0.0", port=8000)

build commands:

$ docker build -t server .
$ docker-slim build --http-probe-cmd / --http-probe-cmd /swagger server
$ docker run -d -p 8000:8000 server.slim

docker-slim logs

docker-slim[build]: info=http.probe message='using default probe'
docker-slim[build]: state=started
docker-slim[build]: info=params target=server continue.mode=probe
docker-slim[build]: state=image.inspection.start
docker-slim[build]: info=image id=sha256:d8969971141e45f473889ab87f57dd68acaf92ec5df8a7c27c94d8b7d00b047b size.bytes=967401912 size.human=967 MB
docker-slim[build]: info=image.stack index=0 name='python:3.7' id='sha256:fbf9f709ca9f5d96dec78cc074963bc44f0497bb73792bf2cd1cb40072ad0f8f'
docker-slim[build]: info=image.stack index=1 name='server:latest' id='sha256:d8969971141e45f473889ab87f57dd68acaf92ec5df8a7c27c94d8b7d00b047b'
docker-slim[build]: info=image.exposed_ports list='8000'
docker-slim[build]: state=image.inspection.done
docker-slim[build]: state=container.inspection.start
docker-slim[build]: info=container status=created name=dockerslimk_12224_20191213145535 id=e3738ea32225295356c81aa41138aeb4d6351c72210442dcf94e219389c95837
docker-slim[build]: info=cmd.startmonitor status=sent
docker-slim[build]: info=event.startmonitor.done status=received
docker-slim[build]: info=container name=dockerslimk_12224_20191213145535 id=e3738ea32225295356c81aa41138aeb4d6351c72210442dcf94e219389c95837 target.port.list=[32776] target.port.info=[8000/tcp => 0.0.0.0:32776] message='YOU CAN USE THESE PORTS TO INTERACT WITH THE CONTAINER'
docker-slim[build]: state=http.probe.starting message='WAIT FOR HTTP PROBE TO FINISH'
docker-slim[build]: info=continue.after mode=probe message='no input required, execution will resume when HTTP probing is completed'
docker-slim[build]: info=prompt message='waiting for the HTTP probe to finish'
docker-slim[build]: state=http.probe.running
docker-slim[build]: info=http.probe.ports count=1 targets='32776'
docker-slim[build]: info=http.probe.commands count=3 commands='GET /,GET /swagger,GET /,...'
docker-slim[build]: info=http.probe.call status=200 method=GET target=http://127.0.0.1:32776/ attempt=1  time=2019-12-13T14:55:48Z
docker-slim[build]: info=http.probe.call status=200 method=GET target=http://127.0.0.1:32776/swagger attempt=1  time=2019-12-13T14:55:48Z
docker-slim[build]: info=http.probe.call status=200 method=GET target=http://127.0.0.1:32776/ attempt=1  time=2019-12-13T14:55:48Z
docker-slim[build]: info=http.probe.summary total=3 failures=0 successful=3
docker-slim[build]: state=http.probe.done
docker-slim[build]: info=event message='HTTP probe is done'
docker-slim[build]: state=container.inspection.finishing
docker-slim[build]: state=container.inspection.artifact.processing
docker-slim[build]: state=container.inspection.done
docker-slim[build]: state=building message='building minified image'
docker-slim[build]: state=completed
docker-slim[build]: info=results status='MINIFIED BY 17.43X [967401912 (967 MB) => 55511032 (56 MB)]'
docker-slim[build]: info=results  image.name=server.slim image.size='56 MB' data=true
docker-slim[build]: info=results  artifacts.location='/tmp/docker-slim-state/.docker-slim-state/images/d8969971141e45f473889ab87f57dd68acaf92ec5df8a7c27c94d8b7d00b047b/artifacts'
docker-slim[build]: info=results  artifacts.report=creport.json
docker-slim[build]: info=results  artifacts.dockerfile.original=Dockerfile.fat
docker-slim[build]: info=results  artifacts.dockerfile.new=Dockerfile
docker-slim[build]: info=results  artifacts.seccomp=server-seccomp.json
docker-slim[build]: info=results  artifacts.apparmor=server-apparmor-profile
docker-slim[build]: state=done
docker-slim[build]: info=report file='slim.report.json'
fulviodan commented 3 years ago

hello, I'm having the same problem when the image is minified with docker-slim? Are there any news on this point? Thanks