{"id":22273561,"url":"https://github.com/dfleta/docker-multistage-maven-java","last_synced_at":"2025-03-25T16:42:00.996Z","repository":{"id":51363760,"uuid":"366873491","full_name":"dfleta/docker-multistage-maven-java","owner":"dfleta","description":"Docker multi-stage: maven build -\u003e jre jar  ","archived":false,"fork":false,"pushed_at":"2021-05-13T11:52:54.000Z","size":1134,"stargazers_count":1,"open_issues_count":1,"forks_count":2,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-01-30T14:45:30.913Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/dfleta.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2021-05-12T22:52:30.000Z","updated_at":"2021-05-16T18:44:25.000Z","dependencies_parsed_at":"2022-09-11T19:23:45.968Z","dependency_job_id":null,"html_url":"https://github.com/dfleta/docker-multistage-maven-java","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dfleta%2Fdocker-multistage-maven-java","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dfleta%2Fdocker-multistage-maven-java/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dfleta%2Fdocker-multistage-maven-java/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dfleta%2Fdocker-multistage-maven-java/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/dfleta","download_url":"https://codeload.github.com/dfleta/docker-multistage-maven-java/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":245501826,"owners_count":20625859,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-12-03T13:13:43.708Z","updated_at":"2025-03-25T16:42:00.973Z","avatar_url":"https://github.com/dfleta.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"Gilded Rose kata\n================\n\nEl código a refactorizar:\n\n[Emily Bache Gilded Rose Kata - Java](https://github.com/emilybache/GildedRose-Refactoring-Kata/tree/master/Java)\n\nLa lógica del negocio:\n\n[Cómo se actualiza la calidad de los items y su fechas de caducidad](https://github.com/dfleta/Python_ejercicios/blob/master/Poo/GildedRose_Refactoring_TDD_Kata/GildedRoseRequirements.txt)\n\n\n## Cómo refactorizar\n\nEn el capítulo 24 del libro _Code Complete_ de Steven C. McConnell encontrarás todas las buenas prácticas que necesitas conocer para refactorizar de manera sistemática. \n\n## Qué es la refactorización\n\nMartin Fowler define la técnica de refactorización como:\n\n_\"a change made to the internal structure of the software to make it easier to understand and cheaper to modify without changing its observable behavior”._\n\nEs, sin duda, la frase que aprendida de memoria más salud y felicidad reportará a tu vida.\n\nEn el caso de la refactorización de la lógica de los productos mágicos de la tienda _Gilded Rose_, según las directrices de _Code Complete_:\n\n - _\"Replace conditionals with polymorphism (especially repeated case statements):_\n    - _Much of the logic that used to be contained in case statements in structured programs can instead be baked into the inheritance hierarchy and accomplished through polymorphic routine calls instead.\"_\n\n - A big refactoring is a recipe for disaster. —Kent Beck  :slack_call: @Elmo \n\nEs decir: para evitar la complejidad provocada por `if-else` anidados y sus correspondientes operadores lógicos vamos a utilizar polimorfismo o el **Principio de Substitución de Liskov (LSP)**(es una mujer, listo) de los principios SOLID.\n\nAdemás, practicaremos TDD añadiendo poco a poco casos test para evitar etapas demasiado grandes de refactorizaciones que nos aboquen a un desastre. \n\n\n## Programación Orientada a Objetos\n\n### Conceptos de Programación Orientada a Objetos:\n\nCap. 1 libro _Beginning Java 8 Fundamentals_.\n\n- **Abstracción**: exponer sólo los detalles esenciales.\n- **Encapsulamiento**: agrupar datos + las operaciones sobre esos datos =\u003e DAT o tipo de dato abstracto (Data Abstract Type).\n- **Herencia**: derivar un DAT de otro, por ejemplo, el xenomorpho de la película _Alien_ (buen spoiler).\n- **Ocultar información**: ocultar detalles de implementación que pueden cambiar.\n- **Polimorfismo**: una entidad soporta diferentes significados en diferentes contextos.\n  - **Coercitivo**: cast de tipos.\n  - **De inclusión**: herencia y sobreescritura (de métodos)\n  - **De sobrecarga** (de métodos).\n  - **Paramétrico**: generics de Java. :mrmeeseeks: Mr. Meeseeks!\n\n### DAT\n\nCapítulo 6: Working Classes, Code Complete:\nhttps://docs.google.com/document/d/1qFJXxEiWWgJPYbPghdB1d6O9TTbNmb3l85VWs-NNDfk\n\n### LSP - SOLID\n\nVamos a aplicar polimorfismo o el **Principio de Substitución de Liskov (LSP)**(es una mujer, listo) de los principios SOLID.\n\nL de SOLID = [Principio de Substitución de Liksov](https://es.wikipedia.org/wiki/Principio_de_sustituci%C3%B3n_de_Liskov)\n\n\n_\"Un tipo de dato abstracto se implementa escribiendo una clase especial de programa que define el tipo en términos de las operaciones que pueden ser realizadas sobre él\"_. Esta es la interpretación **_duck typing_**.\n\n_\"Los subtipos deben ser substituibles por sus tipos básicos\"_. Martin C. Robert.\n\n_\"Se acepta normalmente que los objetos deben ser modificados unicamente a través de sus métodos (Encapsulamiento). Como los subtipos pueden introducir nuevos métodos, ausentes en el supertipo, estos podrían cambiar el estado interno del objeto en formas que serían imposibles o inadmisibles en el supertipo. La restricción histórica impide este tipo de modificaciones.\"_\n\n## Diagrama de clase UML\n\nUtiliza este diagrama de clases UML para guiarte en la implementación de las clases:\n\n![Diagrama de clases UML](./diagrama_clases_UML.jpg)\n\nBásicamente, es el mismo diseño que entre todas las personas de clase hemos discurrido de manera colaborativa:\n\n![Proto UML](./diseño%20colaborativo%20protoUML.jpg)\n\n\nJAVA en un docker - multistage\n==============================\n\nImágenes:\n\nhttps://github.com/docker-library/docs/tree/master/openjdk\n\nhttps://hub.docker.com/_/openjdk\n\n\n## Single stage - OpenJDK JRE\nCrear la imagen con el JDK y el JRE para crear los `jar` de la app:\n\n`Dockerfile`\n\n```Dockerfile\nFROM openjdk:11.0-jre-slim-buster\n\nLABEL \"edu.elsmancs.gildedrose\"=\"Kata Gilded Rose\"\nLABEL version=\"1.0\"\nLABEL description=\"Kata Gilded Rose en Java\"\nLABEL maintainer=\"davig@cifpfbmoll.eu\"\n\nWORKDIR $HOME/app\n\nCOPY ./target/gildedrose-1.0-SNAPSHOT.jar ./app/gildedrose.jar\n\nCMD [\"java\", \"-jar\", \"./app/gildedrose.jar\"]\n```\n\n### Crear la imagen\n\n```bash\n$ docker build -t gildedrose .\n\n$ docker images \n\nREPOSITORY       TAG                    IMAGE ID       CREATED         SIZE\ngildedrose       latest                 97ba7872c8f5   4 minutes ago   220MB\nopenjdk          11.0-jre-slim-buster   4f4564121f23   3 days ago      220MB\n```\n\n### Crear un contenedor y ejecutarlo a partir de la imagen:\n\n```bash\n$ docker run -it --name katagildedrose gildedrose:latest\n\nBienvenido a Ollivanders!\n         ####  DAY 1 ####\nname=+5 Dexterity Vest, sell_in=10, quality=20\nname=Aged Brie, sell_in=2, quality=0\nname=Elixir of the Mongoose, sell_in=5, quality=7\nname=Sulfuras, Hand of Ragnaros, sell_in=0, quality=80\nname=Sulfuras, Hand of Ragnaros, sell_in=-1, quality=80\nname=Backstage passes to a TAFKAL80ETC concert, sell_in=15, quality=20\n...\n\n$ docker ps -a\n\nCONTAINER ID   IMAGE                COMMAND        CREATED         STATUS       PORTS     NAMES\n88aa8adfa8ec   gildedrose:latest   \"java -jar ./app/gil…\"   10 minutes ago   Exited (0) 10 minutes ago   katagildedrose\n```\n\nNo necesito de momento el -dockerignore porque no estoy copiando código fuente, sólo los `jar`\n\n## multi-stage\n\nMejor usar la imagen maven oficial porque al instalar por mi cuenta maven en la imagen da problemas: \n\nhttps://hub.docker.com/_/maven\n\nLeer el dockerfile\n\nSe generan la imagen maven, la openjdk, y una \u003cnone\u003e que me cargo luego, más la final con jre+la app\n\nEsta manera me permite construir la app con maven en una imagen maven (a la que he copiado el código fuente) y copiar sólo el jar a otra imagen, de modo que si publico la imagen no se puede acceder al fuente. Además, la imagen con maven pesa 400MB mientras que la jre sólo 200MB.\n\n```Dockerfile\n# Imagen base\n## BUILD STAGE =\u003e maven build ##\nFROM maven:3.6.3-openjdk-11-slim AS build\n\n# copia en la ruta indicada \n# (si es relativa desde el workdir)\nCOPY . /usr/src/app\n\n# desde el workdir si se indica ruta relativa\nRUN mvn -f /usr/src/app/pom.xml clean package\n\n\n## PACKAGE STAGE =\u003e Imagen runable con el jar de la app ##\n\nFROM openjdk:11.0-jre-slim-buster\n\nLABEL \"edu.elsmancs.gildedrose\"=\"Kata Gilded Rose\" \\\n        version=\"1.0\" \\\n        description=\"Kata Gilded Rose en Java\" \\ \n        maintainer=\"davig@cifpfbmoll.eu\"\n\nWORKDIR $HOME/app \n\n# copiar el jar desde el stage build al workdir del docker\nCOPY --from=build /usr/src/app/target/*.jar ./gildedrose.jar\n\n# ejecutar este comando al ejecutar el docker\nENTRYPOINT [\"java\", \"-jar\", \"gildedrose.jar\"]\n```\n\n-----------------\n\nArrancar mi docker **sobreescribiendo el entrypoint** y así poder ejecutarlo en modo interactivo\n\n```bash\n$ docker run --rm -it --entrypoint=/bin/bash mavenrose:latest \n\nroot@0d8424b096f8:/app# ls\ngildedrose.jar\n\nroot@0d8424b096f8:/app# java -jar gildedrose.jar\n\nroot@0d8424b096f8:/app# exit\n```\n-----------------\n\nEjecutar el contenedor tal cual:\n\n```bash\n$ docker start -i gildedrose \n\n$ docker container run -it --rm mavenrose:latest \n```\n\n-----------------\n\n\nVer el **historial de capas** de la imagen:\n\n```bash\n$ docker image history mavenrose:latest\n\nage history mavenrose:latest\nIMAGE          CREATED        CREATED BY                                      SIZE      COMMENT\n66b0ba2acab1   3 months ago   /bin/sh -c #(nop)  ENTRYPOINT [\"java\" \"-jar\"…   0B        \n8ffc2b695386   3 months ago   /bin/sh -c #(nop) COPY file:0c8b69203defcdcb…   9.6kB     \n7b9f1245a45f   3 months ago   /bin/sh -c #(nop) WORKDIR /app                  0B        \nb9b7d6f69027   3 months ago   /bin/sh -c #(nop)  LABEL edu.elsmancs.gilded…   0B        \n4f4564121f23   3 months ago   /bin/sh -c set -eux;   arch=\"$(dpkg --print-…   142MB     \n\u003cmissing\u003e      3 months ago   /bin/sh -c #(nop)  ENV JAVA_VERSION=11.0.10     0B        \n\u003cmissing\u003e      3 months ago   /bin/sh -c #(nop)  ENV LANG=C.UTF-8             0B        \n\u003cmissing\u003e      3 months ago   /bin/sh -c #(nop)  ENV PATH=/usr/local/openj…   0B        \n\u003cmissing\u003e      3 months ago   /bin/sh -c { echo '#/bin/sh'; echo 'echo \"$J…   27B       \n\u003cmissing\u003e      3 months ago   /bin/sh -c #(nop)  ENV JAVA_HOME=/usr/local/…   0B        \n\u003cmissing\u003e      4 months ago   /bin/sh -c set -eux;  apt-get update;  apt-g…   8.78MB    \n\u003cmissing\u003e      4 months ago   /bin/sh -c #(nop)  CMD [\"bash\"]                 0B        \n\u003cmissing\u003e      4 months ago   /bin/sh -c #(nop) ADD file:422aca8901ae3d869…   69.2MB    \n```\n\nLa capa superior es la última. A medida que descedemos las capas son más antiguas. La capa superior es la que generalmente usamos para ejecutar los contendores. \n\n-----------------\n\nPara ver los **metadata** de la imagen que hemos creado con `LABEL (key=value)`: \n\n```bash\n$ docker image inspect mavenrose:latest \n...\n \"Labels\": {\n                \"description\": \"Kata Gilded Rose en Java\",\n                \"edu.elsmancs.gildedrose\": \"Kata Gilded Rose\",\n                \"maintainer\": \"davig@cifpfbmoll.eu\",\n                \"version\": \"1.0\"\n            }\n```\n\n-----------------\n\n**Publicar la imagen** en dockerhub\n\n```bash\n~$ docker tag mavenrose:latest dfleta/gildedrose\n\n~$ docker login -u \u003cuser\u003e\n```\n\n-----------\n\nComandos útiles\n\n```bash\n$ docker container rm id_contenedor\n\n$ docker images\n\n$ docker image rm id_imagen\n\n$ docker start contenedor\n$ docker stop contenedor\n\n$ docker ps -a\n```\n\n### Docker handbook de freecodecamp\n\nhttps://www.freecodecamp.org/news/the-docker-handbook/","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdfleta%2Fdocker-multistage-maven-java","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdfleta%2Fdocker-multistage-maven-java","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdfleta%2Fdocker-multistage-maven-java/lists"}