Skip to content

Conversation

@jimschubert
Copy link
Contributor

I recently created https://hub.docker.com/r/jimschubert/swagger-codegen-cli/ to allow running Swagger Codegen without installing Java. I had looked around at other containers, but they were all 650MB+. It was suggested that I incorporate my changes into the main repo, so I'm opening this pull request for feedback.

Here are the sizes of the containers with my changes:

$ docker images
REPOSITORY                      TAG                 IMAGE ID            CREATED             SIZE
swagger-api/swagger-codegen     latest              51ff24914193        6 minutes ago       219.9 MB
swagger-api/swagger-generator   latest              aaae2abfa892        17 minutes ago      188.9 MB

In comparison, the current swagger-api/swagger-generator image is 687MiB (from https://imagelayers.io/?images=swaggerapi%2Fswagger-generator:latest):

This change reduces the image for Swagger Generator to 189MB.

There's currently no Swagger Codegen official image, but local builds against the previous Swagger Codegen Dockerfile resulted in a ~630MB image. New size is 220MB.

@arnested @wing328

@jimschubert
Copy link
Contributor Author

I should add... the run-in-docker.sh doesn't use the Dockerfile, it uses the previous heavy maven:3.3-jdk-7 image. These changes shouldn't affect anyone using that script. The maven repository cache is in a different place in my base image, so the rm -rf on the maven cache shouldn't matter... it should either just pull the maven dependencies on demand or complain about the mapping depending on the version of Docker.

I'd like to include instructions in the README, but I wanted to get some opinions. Currently, the README lists the swagger-generator web application as the Docker image. What would be the best way to present the difference between these two? I'd say the main Docker container would be akin to the swagger-codegen which gets installed via homebrew, allowing developers to run swagger-codegen without upgrading or installing Java. The Swagger Generator container would be a self-hosted option for developers to generate code ad-hoc while the swagger-generator container could be integrated into CI pipelines.

@ePaul
Copy link
Contributor

ePaul commented May 24, 2016

I don't really use the CLI version (but the maven-plugin instead – of course that is an option just for maven-based builds), but this sounds nice.

Why is the CLI version 31 MB bigger than the webapp? I would have expected it the other way around, if at all.

It looks like one of then includes the build process in the dockerfile, while the other one just takes the result. Maybe here we have some more optimization possibilities (or, possibly, we could share some layers between both).

What would be the best way to present the difference between these two? I'd say the main Docker container would be akin to the swagger-codegen which gets installed via homebrew, allowing developers to run swagger-codegen without upgrading or installing Java.

Sounds right.

The Swagger Generator container would be a self-hosted option for developers to generate code ad-hoc while the swagger-generator container could be integrated into CI pipelines.

This sentence has twice "swagger generator"?

@jimschubert
Copy link
Contributor Author

jimschubert commented May 24, 2016

@ePaul thanks for the feedback. That second swagger-generator should read swagger-codegen. The point about ci being devs could use swagger-codegen in non-Java pipelines and on systems which admins don't usually want Java installed (like TFS).

Edited. My autocorrect is going bananas.

@jimschubert
Copy link
Contributor Author

@ePaul about your other question, the CLI version is larger because it includes the full source plus the compiled jar, whereas the swagger-generator version includes only the pre-built war and jetty jar files.

@arnested
Copy link
Contributor

@jimschubert, I gave it another try tonight and it worked just perfect! The problems I described earlier today on Gitter have disappeared (I probably messed something up while trying to get coffee, prepare for daily standup, and checking Faceb^H^H^H^H^H work e-mail).

The image size for swagger-codegen is 219.8 MB on my machine (Docker 1.10.0).

But if the purpose of this is to provide an official image on Docker Hub we could reduce size even more by using the same method as for the swagger-generator image: let Travis CI do its build, create an image with just the jar file, and push it to Docker Hub.

We could achieve this by adding a modules/swagger-codegen-cli/Dockerfile like this one (and adding a step to .travis.yml):

FROM java:8-jdk-alpine

ADD target/swagger-codegen-cli.jar /opt/swagger-codegen-cli/swagger-codegen-cli.jar

ENTRYPOINT ["java", "-jar", "/opt/swagger-codegen-cli/swagger-codegen-cli.jar"]
CMD ["help"]

The result is 160.1 MB -- that's additionally 60 MB saved.

That would fulfil the purpose of providing an official image on Docker Hub.

If the purpose is to provide a way to build your own swagger-codegen-cli without having Java installed we definitely need what you have created. (And maybe we could have both -- not sure whether 60 MB saved can justify the extra setup and maintenance).

No matter what approach we should also add some documentation on usage somewhere (especially something about what one should do with volumes). But that could be for another pull request.

@jimschubert
Copy link
Contributor Author

I think that's some great feedback. Your proposal (and my changes to swagger-generator) could probably save even more by using java:8-jre-alpine instead of the jdk image.

@jimschubert
Copy link
Contributor Author

@arnested I've incorporated your feedback. New sizes:

swagger-api/swagger-generator   latest              3f1758dc7ee8        5 minutes ago       141.7 MB
swagger-api/swagger-codegen     latest              3841709002b6        6 minutes ago       122.9 MB

I like your suggestion to keep the Dockerfile in the root as a development container. I think I'll add back the maven repository volume mapping and remove the mvn clean and removing the repository cache.

I'll also add a docker entrypoint script to allow users to run the container with an interactive shell. Right now and previously, it would only act as a swagger-codegen executable. I may also be able to incorporate this change into the run-in-docker.sh script.

This update allows the root Dockerfile to be used as a development
container and updates run-in-docker.sh to use the same entrypoint script
while maintaining backward compatibility for anyone who has scripted
mappings to /gen and /root/.m2/repository.
@jimschubert
Copy link
Contributor Author

@arnested I've updated the Dockerfile in the repo root to be a development container per your recommendation. I've also updated the run-in-docker.sh script to work the same as the root Dockerfile, although it still uses the heavier base image. I didn't want to modify that script too heavily in case anyone has incorporated it into their development workflow.

To recap, changes thus far:

  • Dockerfile
    • build and run a development image
    • Execute CLI commands directly: generate|help|langs|meta|config-help
  • modules/swagger-codegen-cli/Dockerfile
    • executable image
    • meant to act as a self-contained CLI executable for those who don't want/need Java 8 installed locally
    • can easily be integrated into CI pipelines
  • modules/swagger-generator/Dockerfile
    • executable image
    • meant to act as a self hosted Swagger Generator site
    • can be integrated into CI, but requires multiple REST queries to generate code

I would still need to document usage and plug the modules/swagger-codegen-cli/Dockerfile into the travis build to get the CLI published to docker hub.

@wing328 is it cool to add modules/swagger-codegen-cli/Dockerfile to the travis.yml scripts and push this CLI container to the official swaggerapi docker hub? Or should that be a separate PR?

@arnested
Copy link
Contributor

@jimschubert, you can't add it to .travis.yml yet. A Docker Hub repository must be created before that. Otherwise you won't have anywhere to push the image to 😄

I don't know who would be able to create a Docker Hub repository though. Maybe @fehguy?

@jimschubert
Copy link
Contributor Author

I updated the readme with instructions.

This would just be blocked on someone created an official swaggerapi/swagger-codegen repository on Docker Hub and updating .travis.yml to generate and push that container.

@wing328
Copy link
Contributor

wing328 commented May 27, 2016

I think @fehguy can help create the official image.

@arnested
Copy link
Contributor

diff --git a/.travis.yml b/.travis.yml
index ea9cf50..f3a1c3a 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -16,7 +16,9 @@ install:

 script:
   - mvn verify -Psamples
-  - if [ $DOCKER_HUB_USERNAME ]; then docker login --email=$DOCKER_HUB_EMAIL --username=$DOCKER_HUB_USERNAME --password=$DOCKER_HUB_PASSWORD && docker build -t $DOCKER_IMAGE_NAME ./modules/swagger-generator && if [ ! -z "$TRAVIS_TAG" ]; then docker tag $DOCKER_IMAGE_NAME:latest $DOCKER_IMAGE_NAME:$TRAVIS_TAG; fi && docker push $DOCKER_IMAGE_NAME; fi
+  - if [ $DOCKER_HUB_USERNAME ]; then docker login --email=$DOCKER_HUB_EMAIL --username=$DOCKER_HUB_USERNAME --password=$DOCKER_HUB_PASSWORD && docker build -t $DOCKER_GENERATOR_IMAGE_NAME ./modules/swagger-generator && if [ ! -z "$TRAVIS_TAG" ]; then docker tag $DOCKER_GENERATOR_IMAGE_NAME:latest $DOCKER_GENERATOR_IMAGE_NAME:$TRAVIS_TAG; fi && docker push $DOCKER_GENERATOR_IMAGE_NAME; fi
+  - if [ $DOCKER_HUB_USERNAME ]; then docker login --email=$DOCKER_HUB_EMAIL --username=$DOCKER_HUB_USERNAME --password=$DOCKER_HUB_PASSWORD && docker build -t $DOCKER_CODEGEN_IMAGE_NAME ./modules/swagger-codegen-cli && if [ ! -z "$TRAVIS_TAG" ]; then docker tag $DOCKER_CODEGEN_IMAGE_NAME:latest $DOCKER_CODEGEN_IMAGE_NAME:$TRAVIS_TAG; fi && docker push $DOCKER_CODEGEN_IMAGE_NAME; fi

 env:
-  - DOCKER_IMAGE_NAME=swaggerapi/swagger-generator
+  - DOCKER_GENERATOR_IMAGE_NAME=swaggerapi/swagger-generator
+  - DOCKER_CODEGEN_IMAGE_NAME=swaggerapi/swagger-codegen

@wing328 wing328 modified the milestones: v2.3.0, v2.2.0 Jul 18, 2016
@wing328 wing328 modified the milestones: v2.2.1, v2.3.0 Aug 8, 2016
@wing328 wing328 added the Docker label Jan 21, 2017
@@ -1,13 +1,22 @@
FROM maven:3.3-jdk-7
FROM jimschubert/8-jdk-alpine-mvn:1.0
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jimschubert is there a reason why you're not pulling a standard base image?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@fehguy At the time I wrote this, there weren't any minimal containers created for standard base images that just needed Java and Maven. Smaller base images such as the one I've created not only reduce bloat in the container, but also reduce security risks.

For example, here's what maven:3.3-jdk-7 does:

  • derives from openjdk:7-jdk
    • which installs multiple zip utilities (bzip2 unzip xz-utils)
    • openjdk:7-jdk derives from buildpack-deps:jessie-scm
      • which installs (bzr, git, mercurial, openssh-client, subversion, procps)
        • buildpack-deps:jessie-scm derives from buildpack-deps:jessie-curl
          • which installs (ca-certificates, curl, wget)
            • buildpack-deps:jessie-curl derives from debian:jessie
              • debian:jessie is a base image.

Compare to what jimschubert/8-jdk-alpine-mvn:1.0 does:

  • installs ca-certificates openssl
  • curls and installs maven manually
  • derives from openjdk:8-jdk-alpine
    • which install java
    • openjdk:8-jdk-alpine derives from alpine:3.4
      • alpine:3.4 is a base image.

There are other points to maven:3.3-jdk-7, which I'll email you directly.

That said, this could just as easily be updated with the contents of the jimschubert/8-jdk-alpine-mvn:1.0 Dockerfile.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants