diff --git a/.github/workflows/docker-embedded-publish.yml b/.github/workflows/docker-embedded-publish.yml index 338e1f2..aca06f3 100644 --- a/.github/workflows/docker-embedded-publish.yml +++ b/.github/workflows/docker-embedded-publish.yml @@ -2,13 +2,21 @@ name: Publish Embedded GlassFish Docker Image to GitHub on: workflow_dispatch: + inputs: + gfVersion: + description: 'The value of the glassfish.version property, used also to build the image.' + required: true + default: '7.1.0' + basicImage: + description: 'The basic docker image' + required: true + default: 'eclipse-temurin:21-jdk' env: # Use docker.io for Docker Hub if empty REGISTRY: ghcr.io # github.repository as / IMAGE_ID: "ghcr.io/${{ github.repository_owner }}/embedded-glassfish" - IMAGE_VERSION: 7.1.0 jobs: build: @@ -24,22 +32,22 @@ jobs: steps: - name: Checkout Repository - uses: actions/checkout@v4 + uses: actions/checkout@v6 - name: Maven Configure - uses: actions/setup-java@v4 + uses: actions/setup-java@v5 with: - java-version: '21' + java-version: '25' distribution: 'temurin' - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 + uses: docker/setup-buildx-action@v5 with: driver: docker-container platforms: linux/amd64,linux/arm64 - name: Build - run: mvn clean prepare-package -Dglassfish.version=$IMAGE_VERSION + run: mvn clean prepare-package -Dglassfish.version=${{ github.event.inputs.gfVersion }} -Dgf.docker.baseImage=${{ github.event.inputs.basicImage }} - name: Log in to registry run: echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u ${{ github.actor }} --password-stdin @@ -54,8 +62,8 @@ jobs: - name: Build and Deploy uses: docker/build-push-action@v6 with: - context: images/embedded/${{ env.IMAGE_VERSION }} + context: images/embedded/${{ github.event.inputs.gfVersion }} platforms: linux/amd64,linux/arm64 push: true - tags: ${{ env.IMAGE_ID }}:${{ env.IMAGE_VERSION }},${{ env.IMAGE_ID }}:latest + tags: ${{ env.IMAGE_ID }}:${{ github.event.inputs.gfVersion }},${{ env.IMAGE_ID }}:latest diff --git a/.github/workflows/docker-server-publish.yml b/.github/workflows/docker-server-publish.yml index edca8db..6d5ab8d 100644 --- a/.github/workflows/docker-server-publish.yml +++ b/.github/workflows/docker-server-publish.yml @@ -2,13 +2,21 @@ name: Publish GlassFish Server Docker Image to GitHub on: workflow_dispatch: + inputs: + gfVersion: + description: 'The value of the glassfish.version property, used also to build the image.' + required: true + default: '7.1.0' + basicImage: + description: 'The basic docker image' + required: true + default: 'eclipse-temurin:21-jdk' env: # Use docker.io for Docker Hub if empty REGISTRY: ghcr.io # github.repository as / IMAGE_ID: "ghcr.io/${{ github.repository_owner }}/glassfish" - IMAGE_VERSION: 7.1.0 jobs: build: @@ -24,22 +32,22 @@ jobs: steps: - name: Checkout Repository - uses: actions/checkout@v4 + uses: actions/checkout@v6 - name: Maven Configure - uses: actions/setup-java@v4 + uses: actions/setup-java@v5 with: - java-version: '21' + java-version: '25' distribution: 'temurin' - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 + uses: docker/setup-buildx-action@v5 with: driver: docker-container platforms: linux/amd64,linux/arm64 - name: Build - run: mvn clean prepare-package -Dglassfish.version=$IMAGE_VERSION + run: mvn clean prepare-package -Dglassfish.version=${{ github.event.inputs.gfVersion }} -Dgf.docker.baseImage=${{ github.event.inputs.basicImage }} - name: Log in to registry run: echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u ${{ github.actor }} --password-stdin @@ -54,8 +62,8 @@ jobs: - name: Build and Deploy uses: docker/build-push-action@v6 with: - context: images/server/${{ env.IMAGE_VERSION }} + context: images/server/${{ github.event.inputs.gfVersion }} platforms: linux/amd64,linux/arm64 push: true - tags: ${{ env.IMAGE_ID }}:${{ env.IMAGE_VERSION }},${{ env.IMAGE_ID }}:latest + tags: ${{ env.IMAGE_ID }}:${{ github.event.inputs.gfVersion }},${{ env.IMAGE_ID }}:latest diff --git a/README.md b/README.md index 4973fb0..9f75617 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Eclipse Glassfish Full Profile Docker Image +# Eclipse Glassfish Docker Images ## Frequently Asked Questions diff --git a/images/server/7.1.0/Dockerfile b/images/server/7.1.0/Dockerfile index 2f92f3c..cd8c956 100755 --- a/images/server/7.1.0/Dockerfile +++ b/images/server/7.1.0/Dockerfile @@ -71,6 +71,7 @@ RUN true \ && asadmin set-log-attributes org.glassfish.main.jul.handler.GlassFishLogHandler.enabled=false \ && asadmin set-log-attributes org.glassfish.main.jul.handler.SimpleLogHandler.level=FINEST \ && asadmin enable-secure-admin \ + && sleep 1 \ && asadmin stop-domain --kill \ && rm -f ${PATH_GF_SERVER_LOG} ${PATH_GF_PASSWORD_FILE_FOR_CHANGE} \ && chown -R glassfish:glassfish "${PATH_GF_HOME}" \ diff --git a/images/server/7.1.0/docker-entrypoint.sh b/images/server/7.1.0/docker-entrypoint.sh index 3ef508d..576a279 100755 --- a/images/server/7.1.0/docker-entrypoint.sh +++ b/images/server/7.1.0/docker-entrypoint.sh @@ -2,37 +2,49 @@ set -e change_passwords () { - local PWD_FILE=/tmp/passwordfile - local COMMAND= - rm -rf $PWD_FILE - - if [ "${AS_ADMIN_PASSWORD}" != "" ] && [ "${AS_ADMIN_PASSWORD}" != "admin" ]; then - echo -e "AS_ADMIN_PASSWORD=admin\nAS_ADMIN_NEWPASSWORD=${AS_ADMIN_PASSWORD}" >> $PWD_FILE - COMMAND="change-admin-password" - echo "AS_ADMIN_PASSWORD=${AS_ADMIN_PASSWORD}" > "${AS_PASSWORD_FILE}" - fi - - if [ "${AS_ADMIN_MASTERPASSWORD}" != "" ] && [ "${AS_ADMIN_MASTERPASSWORD}" != "changeit" ]; then - echo -e "AS_ADMIN_MASTERPASSWORD=changeit\nAS_ADMIN_NEWMASTERPASSWORD=${AS_ADMIN_MASTERPASSWORD}" >> ${PWD_FILE} - COMMAND="${COMMAND}\nchange-master-password --savemasterpassword=true" - fi - - if [ "${COMMAND}" != "" ]; then - echo -e "${COMMAND}" | asadmin --interactive=false --passwordfile=${PWD_FILE} - fi - - rm -rf ${PWD_FILE} - history -c + local PATH_GF_PASSWORD_FILE_FOR_CHANGE=/tmp/passwordfile + local COMMAND="" + rm -f "${PATH_GF_PASSWORD_FILE_FOR_CHANGE}" + + if [ "${AS_ADMIN_PASSWORD}" != "" ] && [ "${AS_ADMIN_PASSWORD}" != "admin" ]; then + echo -e "AS_ADMIN_PASSWORD=admin" > "${PATH_GF_PASSWORD_FILE_FOR_CHANGE}" + echo -e "AS_ADMIN_NEWPASSWORD=${AS_ADMIN_PASSWORD}" >> "${PATH_GF_PASSWORD_FILE_FOR_CHANGE}" + COMMAND="change-admin-password" + fi + + if [ "${AS_ADMIN_MASTERPASSWORD}" != "" ] && [ "${AS_ADMIN_MASTERPASSWORD}" != "changeit" ]; then + echo -e "AS_ADMIN_MASTERPASSWORD=changeit" >> ${PATH_GF_PASSWORD_FILE_FOR_CHANGE} + echo -e "AS_ADMIN_NEWMASTERPASSWORD=${AS_ADMIN_MASTERPASSWORD}" >> ${PATH_GF_PASSWORD_FILE_FOR_CHANGE} + COMMAND+="\nchange-master-password --savemasterpassword=true" + fi + + if [ "${COMMAND}" != "" ]; then + echo -e "${COMMAND}" | asadmin --interactive=false --passwordfile=${PATH_GF_PASSWORD_FILE_FOR_CHANGE} + echo "AS_ADMIN_PASSWORD=${AS_ADMIN_PASSWORD}" > "${AS_PASSWORD_FILE}" + fi + + rm -f ${PATH_GF_PASSWORD_FILE_FOR_CHANGE} + unset AS_ADMIN_PASSWORD; + unset AS_ADMIN_MASTERPASSWORD; + history -c +} + +on_exit () { + EXIT_CODE=$? + set +e; + ps -lAf; + asadmin stop-domain --force --kill; + exit $EXIT_CODE; } change_passwords if [ -f custom/init.sh ]; then - /bin/bash custom/init.sh + /bin/bash custom/init.sh fi if [ -f custom/init.asadmin ]; then - asadmin --interactive=false multimode -f custom/init.asadmin + asadmin --interactive=false multimode -f custom/init.asadmin fi @@ -43,25 +55,17 @@ fi CONTAINER_ALREADY_STARTED="CONTAINER_ALREADY_STARTED_PLACEHOLDER" if [ ! -f "$CONTAINER_ALREADY_STARTED" ] then - touch "$CONTAINER_ALREADY_STARTED" && - rm -rf glassfish/domains/domain1/autodeploy/.autodeploystatus || true + touch "$CONTAINER_ALREADY_STARTED" && rm -rf glassfish/domains/domain1/autodeploy/.autodeploystatus fi if [ "${AS_TRACE}" == true ]; then - env|sort + env | sort fi if [ "$1" == 'startserv' ]; then - exec "$@" + exec "$@" fi -on_exit () { - EXIT_CODE=$? - set +e; - ps -lAf; - asadmin stop-domain --force --kill; - exit $EXIT_CODE; -} trap on_exit EXIT "$@" & wait diff --git a/images/server/7.1.0/docs/content.md b/images/server/7.1.0/docs/content.md index 42cc286..2878c77 100644 --- a/images/server/7.1.0/docs/content.md +++ b/images/server/7.1.0/docs/content.md @@ -13,13 +13,13 @@ Run GlassFish with the following command: ``` -docker run -p 8080:8080 -p 4848:4848 @docker.glassfish.repository@ +docker run -p 8080:8080 -p 4848:4848 glassfish ``` Or with a command for a specific tag (GlassFish version): ``` -docker run -p 8080:8080 -p 4848:4848 @docker.glassfish.image@ +docker run -p 8080:8080 -p 4848:4848 glassfish:7.1.0 ``` Open the following URLs in the browser: @@ -52,13 +52,13 @@ Follow these steps: 3. Run the following command to start GlassFish in Docker with your application, where `/deployments` is path to the directory created in step 1, and /deploy is the directory in the container where GlassFish expects applications: ``` -docker run -p 8080:8080 -p 4848:4848 -v /deployments:/deploy @docker.glassfish.repository@ +docker run -p 8080:8080 -p 4848:4848 -v /deployments:/deploy glassfish ``` Alternatively, you can mount a specific WAR file directly: ``` -docker run -p 8080:8080 -p 4848:4848 -v /deployment/application.war:/deploy/application.war @docker.glassfish.repository@ +docker run -p 8080:8080 -p 4848:4848 -v /deployment/application.war:/deploy/application.war glassfish ``` **Note**: GlassFish Server deploys applications using the WAR filename as the context path (e.g., `application.war` becomes accessible at `/application/`). @@ -74,7 +74,7 @@ The context root (`application`) is derived from the name of the application fil You can modify the start command of the Docker container to `startserv --debug` to enable debug mode. You should also map the debug port 9009. ``` -docker run -p 9009:9009 -p 8080:8080 -p 4848:4848 @docker.glassfish.repository@ startserv --debug +docker run -p 9009:9009 -p 8080:8080 -p 4848:4848 glassfish startserv --debug ``` Then connect your debugger to the port 9009 on `localhost`. @@ -82,7 +82,7 @@ Then connect your debugger to the port 9009 on `localhost`. If you need suspend GlassFish startup until you connect the debugger, use the `--suspend` argument instead: ``` -docker run -p 9009:9009 -p 8080:8080 -p 4848:4848 @docker.glassfish.repository@ startserv --suspend +docker run -p 9009:9009 -p 8080:8080 -p 4848:4848 glassfish startserv --suspend ``` ## Environment variables @@ -117,7 +117,7 @@ However, always consider to executing any asadmin configuration commands during Just create a file `${PATH_GF_HOME}/custom/init.asadmin` (`/opt/glassfish7/custom/init.asadmin`), the commands will be executed before GlassFish server starts. -Within the `init.asadmin` file, you can specify any asadmin command. Most of the commands require that the server is running, so you'll need to start the server first, run the configuration commands, and then stop the server. +Within the `init.asadmin` file, you can specify any asadmin command. Most of the commands require that the server is running, so you'll need to start the server first, run the configuration commands, and then stop the server. For example, to start GlassFish, increase the maximum amount of threads, and then stop it, the `init.asadmin` file can contain: @@ -130,7 +130,7 @@ stop-domain You can provide the file by mounting its directory to the `/opt/glassfish7/custom` directory in the container when running the container: ``` -docker run -v ./custom:/opt/glassfish7/custom -p 8080:8080 -ti @docker.glassfish.repository@ +docker run -v ./custom:/opt/glassfish7/custom -p 8080:8080 -ti glassfish ``` ### Execute a `bash` script before server startup @@ -156,7 +156,7 @@ stop-domain" | asadmin --interactive=false You can provide the script by mounting its directory to the `/opt/glassfish7/custom` directory in the container when running the container: ``` -docker run -v ./custom:/opt/glassfish7/custom -p 8080:8080 -ti @docker.glassfish.repository@ +docker run -v ./custom:/opt/glassfish7/custom -p 8080:8080 -ti glassfish ``` ### Execute `asadmin` commands during Docker image build @@ -168,7 +168,7 @@ To do it, simply add `RUN instructions that run `asadmin` script with the usual File `Dockerfile`: ``` -FROM @docker.glassfish.repository@ +FROM glassfish RUN printf "start-domain \n \ set configs.config.server-config.thread-pools.thread-pool.http-thread-pool.max-thread-pool-size=1000 \n \ @@ -188,7 +188,7 @@ stop-domain File `Dockerfile`: ``` -FROM @docker.glassfish.repository@ +FROM glassfish COPY commands.asadmin commands.asadmin @@ -202,7 +202,7 @@ Let's try something more complicated. * To modify startup arguments for GlassFish, just add `startserv` to the command line and then add any arguments supported by the `asadmin start-domain` command. The `startserv` script is an alias to the `asadmin start-domain` command but starts GlassFish in a more efficient way that is more suitable in Docker container. For example, to start in debug mode with a custom domain, run: ```bash -docker run @docker.glassfish.repository@ startserv --debug mydomain +docker run glassfish startserv --debug mydomain ``` * Environment variable `AS_TRACE=true` enables tracing of the GlassFish startup. It is useful when the server doesn't start without any useful logs. @@ -212,13 +212,13 @@ docker run @docker.glassfish.repository@ startserv --debug mydomain * `docker run` with `-d` starts the container as a daemon, so the shell doesn't print logs and finishes. Docker then returns the container id which you can use for further commands. ```bash -docker run -d @docker.glassfish.repository@ +docker run -d glassfish ``` Example of running a Docker container in background, view the logs, and then stop it (with debug enabled, trace logging, and user `1000` convenient for Kubernetes ): ```bash -docker run -d -e AS_TRACE=true --user 1000 @docker.glassfish.repository@ startserv --debug=true +docker run -d -e AS_TRACE=true --user 1000 glassfish startserv --debug=true 5a11f2fe1a9dd1569974de913a181847aa22165b5015ab20b271b08a27426e72 docker logs 5a11f2fe1a9dd1569974de913a181847aa22165b5015ab20b271b08a27426e72 @@ -242,7 +242,7 @@ If you want to run more complicated tests, the good path is to public class WelcomePageITest { @Container - private final GenericContainer server = new GenericContainer<>("@docker.glassfish.image@").withExposedPorts(8080); + private final GenericContainer server = new GenericContainer<>("glassfish:7.1.0").withExposedPorts(8080); @Test void getRoot() throws Exception { diff --git a/images/server/7.1.0/docs/logo.svg b/images/server/7.1.0/docs/logo.svg index 55b2329..8234067 100644 --- a/images/server/7.1.0/docs/logo.svg +++ b/images/server/7.1.0/docs/logo.svg @@ -1,35 +1,35 @@ - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + \ No newline at end of file diff --git a/pom.xml b/pom.xml index 68c6b02..a277ab0 100644 --- a/pom.xml +++ b/pom.xml @@ -12,25 +12,25 @@ 7.1.0 + UTF-8 - linux/amd64,linux/arm64 - ${glassfish.version} - eclipse-temurin:21-jdk - glassfish - ${server.docker.glassfish.repository}:${server.docker.glassfish.tag} - images/server - ${basedir}/${server.relative.dir} - src/main/resources/${server.relative.dir} + eclipse-temurin:21-jdk + linux/amd64,linux/arm64 + + images/embedded + ${basedir}/${gf.docker.embedded.dir.relative}/${gf.docker.embedded.tag} + src/main/resources/${gf.docker.embedded.dir.relative} + embedded-glassfish + ${gf.docker.server.tag} + ${gf.docker.embedded.repository}:${gf.docker.embedded.tag} - ${server.docker.platforms} - ${server.docker.glassfish.tag} - ${server.docker.baseImage} - embedded-glassfish - ${embedded.docker.glassfish.repository}:${embedded.docker.glassfish.tag} - images/embedded - ${basedir}/${embedded.relative.dir} - src/main/resources/${embedded.relative.dir} + images/server + src/main/resources/${gf.docker.server.dir.relative} + ${basedir}/${gf.docker.server.dir.relative}/${gf.docker.server.tag} + glassfish + ${glassfish.version} + ${gf.docker.server.repository}:${gf.docker.server.tag} @@ -43,7 +43,7 @@ org.junit.jupiter junit-jupiter-engine - 5.12.1 + 6.0.2 test @@ -55,7 +55,7 @@ org.testcontainers testcontainers - 1.21.4 + 2.0.3 test @@ -70,7 +70,6 @@ maven-enforcer-plugin - 3.5.0 @@ -89,7 +88,6 @@ maven-dependency-plugin - 3.8.1 ${project.build.directory} true @@ -121,7 +119,6 @@ org.codehaus.mojo exec-maven-plugin - 3.5.0 server.computeSha512 @@ -161,7 +158,6 @@ org.codehaus.mojo properties-maven-plugin - 1.2.1 server.load-sha512 @@ -191,12 +187,6 @@ maven-resources-plugin - 3.3.1 - - @ - UTF-8 - true - filter-server-dockerfile @@ -205,10 +195,10 @@ prepare-package - ${server.images.dir}/${server.docker.glassfish.tag} + ${gf.docker.server.dir.target} - ${server.resources.dir} + ${gf.docker.server.dir.source} Dockerfile dockerlibfile-fragment.txt @@ -217,7 +207,7 @@ true - ${server.resources.dir} + ${gf.docker.server.dir.source} docker-entrypoint.sh @@ -233,10 +223,10 @@ prepare-package - ${embedded.images.dir}/${embedded.docker.glassfish.tag} + ${gf.docker.embedded.dir.target} - ${embedded.resources.dir} + ${gf.docker.embedded.dir.source} Dockerfile @@ -250,7 +240,6 @@ io.fabric8 docker-maven-plugin - 0.45.1 build-docker-image @@ -264,42 +253,60 @@ true - ${server.docker.glassfish.repository} + ${gf.docker.server.repository} - ${server.docker.platforms} + ${gf.docker.platforms} - ${server.docker.glassfish.tag} + ${gf.docker.server.tag} none - false - ${server.images.dir}/${server.docker.glassfish.tag}/Dockerfile + true + ${gf.docker.server.dir.target}/Dockerfile @ - ${embedded.docker.glassfish.repository} + ${gf.docker.embedded.repository} - ${embedded.docker.platforms} + ${gf.docker.platforms} - ${embedded.docker.glassfish.tag} + ${gf.docker.embedded.tag} none - false - ${embedded.images.dir}/${embedded.docker.glassfish.tag}/Dockerfile + true + ${gf.docker.embedded.dir.target}/Dockerfile @ + + maven-war-plugin + + + build-test-app + pre-integration-test + + war + + + src/test/webapp + ${project.build.directory}/test-classes + application + test + + + + maven-failsafe-plugin @@ -319,39 +326,57 @@ - - maven-war-plugin - 3.4.0 - - - build-test-app - test-compile - - war - - - src/test/webapp - ${project.build.directory}/test-classes - application - test - - - - + + + maven-enforcer-plugin + 3.6.2 + + + maven-dependency-plugin + 3.9.0 + + + org.codehaus.mojo + exec-maven-plugin + 3.6.3 + + + org.codehaus.mojo + properties-maven-plugin + 1.3.0 + + + maven-resources-plugin + 3.4.0 + + @ + UTF-8 + true + + + + io.fabric8 + docker-maven-plugin + 0.48.0 + maven-compiler-plugin - 3.13.0 + 3.14.1 21 + + maven-war-plugin + 3.5.1 + org.apache.maven.plugins maven-surefire-plugin - 3.5.1 + 3.5.4 **/*Test.java @@ -361,11 +386,11 @@ org.apache.maven.plugins maven-failsafe-plugin - 3.5.1 + 3.5.4 - ${server.docker.glassfish.image} - ${embedded.docker.glassfish.image} + ${gf.docker.server.image} + ${gf.docker.embedded.image} **/*IT.java @@ -374,14 +399,14 @@ maven-install-plugin - 3.1.3 + 3.1.4 true maven-deploy-plugin - 3.1.3 + 3.1.4 true diff --git a/src/main/resources/images/embedded/Dockerfile b/src/main/resources/images/embedded/Dockerfile index 9a12017..b46ffdb 100644 --- a/src/main/resources/images/embedded/Dockerfile +++ b/src/main/resources/images/embedded/Dockerfile @@ -1,6 +1,6 @@ -FROM @embedded.docker.baseImage@ +FROM @gf.docker.baseImage@ -LABEL org.opencontainers.image.base.name="@embedded.docker.baseImage@" +LABEL org.opencontainers.image.base.name="@gf.docker.baseImage@" LABEL org.opencontainers.image.source="https://github.com/eclipse-ee4j/glassfish.docker" LABEL org.opencontainers.image.url="https://github.com/eclipse-ee4j/glassfish.docker/wiki" diff --git a/src/main/resources/images/server/Dockerfile b/src/main/resources/images/server/Dockerfile index c7cb769..0841213 100755 --- a/src/main/resources/images/server/Dockerfile +++ b/src/main/resources/images/server/Dockerfile @@ -1,6 +1,6 @@ -FROM @server.docker.baseImage@ +FROM @gf.docker.baseImage@ -LABEL org.opencontainers.image.base.name="@server.docker.baseImage@" +LABEL org.opencontainers.image.base.name="@gf.docker.baseImage@" LABEL org.opencontainers.image.source="https://github.com/eclipse-ee4j/glassfish.docker" LABEL org.opencontainers.image.url="https://github.com/eclipse-ee4j/glassfish.docker/wiki" @@ -71,6 +71,7 @@ RUN true \ && asadmin set-log-attributes org.glassfish.main.jul.handler.GlassFishLogHandler.enabled=false \ && asadmin set-log-attributes org.glassfish.main.jul.handler.SimpleLogHandler.level=FINEST \ && asadmin enable-secure-admin \ + && sleep 1 \ && asadmin stop-domain --kill \ && rm -f ${PATH_GF_SERVER_LOG} ${PATH_GF_PASSWORD_FILE_FOR_CHANGE} \ && chown -R glassfish:glassfish "${PATH_GF_HOME}" \ diff --git a/src/main/resources/images/server/docker-entrypoint.sh b/src/main/resources/images/server/docker-entrypoint.sh index 3ef508d..576a279 100755 --- a/src/main/resources/images/server/docker-entrypoint.sh +++ b/src/main/resources/images/server/docker-entrypoint.sh @@ -2,37 +2,49 @@ set -e change_passwords () { - local PWD_FILE=/tmp/passwordfile - local COMMAND= - rm -rf $PWD_FILE - - if [ "${AS_ADMIN_PASSWORD}" != "" ] && [ "${AS_ADMIN_PASSWORD}" != "admin" ]; then - echo -e "AS_ADMIN_PASSWORD=admin\nAS_ADMIN_NEWPASSWORD=${AS_ADMIN_PASSWORD}" >> $PWD_FILE - COMMAND="change-admin-password" - echo "AS_ADMIN_PASSWORD=${AS_ADMIN_PASSWORD}" > "${AS_PASSWORD_FILE}" - fi - - if [ "${AS_ADMIN_MASTERPASSWORD}" != "" ] && [ "${AS_ADMIN_MASTERPASSWORD}" != "changeit" ]; then - echo -e "AS_ADMIN_MASTERPASSWORD=changeit\nAS_ADMIN_NEWMASTERPASSWORD=${AS_ADMIN_MASTERPASSWORD}" >> ${PWD_FILE} - COMMAND="${COMMAND}\nchange-master-password --savemasterpassword=true" - fi - - if [ "${COMMAND}" != "" ]; then - echo -e "${COMMAND}" | asadmin --interactive=false --passwordfile=${PWD_FILE} - fi - - rm -rf ${PWD_FILE} - history -c + local PATH_GF_PASSWORD_FILE_FOR_CHANGE=/tmp/passwordfile + local COMMAND="" + rm -f "${PATH_GF_PASSWORD_FILE_FOR_CHANGE}" + + if [ "${AS_ADMIN_PASSWORD}" != "" ] && [ "${AS_ADMIN_PASSWORD}" != "admin" ]; then + echo -e "AS_ADMIN_PASSWORD=admin" > "${PATH_GF_PASSWORD_FILE_FOR_CHANGE}" + echo -e "AS_ADMIN_NEWPASSWORD=${AS_ADMIN_PASSWORD}" >> "${PATH_GF_PASSWORD_FILE_FOR_CHANGE}" + COMMAND="change-admin-password" + fi + + if [ "${AS_ADMIN_MASTERPASSWORD}" != "" ] && [ "${AS_ADMIN_MASTERPASSWORD}" != "changeit" ]; then + echo -e "AS_ADMIN_MASTERPASSWORD=changeit" >> ${PATH_GF_PASSWORD_FILE_FOR_CHANGE} + echo -e "AS_ADMIN_NEWMASTERPASSWORD=${AS_ADMIN_MASTERPASSWORD}" >> ${PATH_GF_PASSWORD_FILE_FOR_CHANGE} + COMMAND+="\nchange-master-password --savemasterpassword=true" + fi + + if [ "${COMMAND}" != "" ]; then + echo -e "${COMMAND}" | asadmin --interactive=false --passwordfile=${PATH_GF_PASSWORD_FILE_FOR_CHANGE} + echo "AS_ADMIN_PASSWORD=${AS_ADMIN_PASSWORD}" > "${AS_PASSWORD_FILE}" + fi + + rm -f ${PATH_GF_PASSWORD_FILE_FOR_CHANGE} + unset AS_ADMIN_PASSWORD; + unset AS_ADMIN_MASTERPASSWORD; + history -c +} + +on_exit () { + EXIT_CODE=$? + set +e; + ps -lAf; + asadmin stop-domain --force --kill; + exit $EXIT_CODE; } change_passwords if [ -f custom/init.sh ]; then - /bin/bash custom/init.sh + /bin/bash custom/init.sh fi if [ -f custom/init.asadmin ]; then - asadmin --interactive=false multimode -f custom/init.asadmin + asadmin --interactive=false multimode -f custom/init.asadmin fi @@ -43,25 +55,17 @@ fi CONTAINER_ALREADY_STARTED="CONTAINER_ALREADY_STARTED_PLACEHOLDER" if [ ! -f "$CONTAINER_ALREADY_STARTED" ] then - touch "$CONTAINER_ALREADY_STARTED" && - rm -rf glassfish/domains/domain1/autodeploy/.autodeploystatus || true + touch "$CONTAINER_ALREADY_STARTED" && rm -rf glassfish/domains/domain1/autodeploy/.autodeploystatus fi if [ "${AS_TRACE}" == true ]; then - env|sort + env | sort fi if [ "$1" == 'startserv' ]; then - exec "$@" + exec "$@" fi -on_exit () { - EXIT_CODE=$? - set +e; - ps -lAf; - asadmin stop-domain --force --kill; - exit $EXIT_CODE; -} trap on_exit EXIT "$@" & wait diff --git a/src/main/resources/images/server/docs/content.md b/src/main/resources/images/server/docs/content.md index 42cc286..cc83c67 100644 --- a/src/main/resources/images/server/docs/content.md +++ b/src/main/resources/images/server/docs/content.md @@ -13,13 +13,13 @@ Run GlassFish with the following command: ``` -docker run -p 8080:8080 -p 4848:4848 @docker.glassfish.repository@ +docker run -p 8080:8080 -p 4848:4848 @gf.docker.server.repository@ ``` Or with a command for a specific tag (GlassFish version): ``` -docker run -p 8080:8080 -p 4848:4848 @docker.glassfish.image@ +docker run -p 8080:8080 -p 4848:4848 @gf.docker.server.image@ ``` Open the following URLs in the browser: @@ -52,13 +52,13 @@ Follow these steps: 3. Run the following command to start GlassFish in Docker with your application, where `/deployments` is path to the directory created in step 1, and /deploy is the directory in the container where GlassFish expects applications: ``` -docker run -p 8080:8080 -p 4848:4848 -v /deployments:/deploy @docker.glassfish.repository@ +docker run -p 8080:8080 -p 4848:4848 -v /deployments:/deploy @gf.docker.server.repository@ ``` Alternatively, you can mount a specific WAR file directly: ``` -docker run -p 8080:8080 -p 4848:4848 -v /deployment/application.war:/deploy/application.war @docker.glassfish.repository@ +docker run -p 8080:8080 -p 4848:4848 -v /deployment/application.war:/deploy/application.war @gf.docker.server.repository@ ``` **Note**: GlassFish Server deploys applications using the WAR filename as the context path (e.g., `application.war` becomes accessible at `/application/`). @@ -74,7 +74,7 @@ The context root (`application`) is derived from the name of the application fil You can modify the start command of the Docker container to `startserv --debug` to enable debug mode. You should also map the debug port 9009. ``` -docker run -p 9009:9009 -p 8080:8080 -p 4848:4848 @docker.glassfish.repository@ startserv --debug +docker run -p 9009:9009 -p 8080:8080 -p 4848:4848 @gf.docker.server.repository@ startserv --debug ``` Then connect your debugger to the port 9009 on `localhost`. @@ -82,7 +82,7 @@ Then connect your debugger to the port 9009 on `localhost`. If you need suspend GlassFish startup until you connect the debugger, use the `--suspend` argument instead: ``` -docker run -p 9009:9009 -p 8080:8080 -p 4848:4848 @docker.glassfish.repository@ startserv --suspend +docker run -p 9009:9009 -p 8080:8080 -p 4848:4848 @gf.docker.server.repository@ startserv --suspend ``` ## Environment variables @@ -117,7 +117,7 @@ However, always consider to executing any asadmin configuration commands during Just create a file `${PATH_GF_HOME}/custom/init.asadmin` (`/opt/glassfish7/custom/init.asadmin`), the commands will be executed before GlassFish server starts. -Within the `init.asadmin` file, you can specify any asadmin command. Most of the commands require that the server is running, so you'll need to start the server first, run the configuration commands, and then stop the server. +Within the `init.asadmin` file, you can specify any asadmin command. Most of the commands require that the server is running, so you'll need to start the server first, run the configuration commands, and then stop the server. For example, to start GlassFish, increase the maximum amount of threads, and then stop it, the `init.asadmin` file can contain: @@ -130,7 +130,7 @@ stop-domain You can provide the file by mounting its directory to the `/opt/glassfish7/custom` directory in the container when running the container: ``` -docker run -v ./custom:/opt/glassfish7/custom -p 8080:8080 -ti @docker.glassfish.repository@ +docker run -v ./custom:/opt/glassfish7/custom -p 8080:8080 -ti @gf.docker.server.repository@ ``` ### Execute a `bash` script before server startup @@ -156,7 +156,7 @@ stop-domain" | asadmin --interactive=false You can provide the script by mounting its directory to the `/opt/glassfish7/custom` directory in the container when running the container: ``` -docker run -v ./custom:/opt/glassfish7/custom -p 8080:8080 -ti @docker.glassfish.repository@ +docker run -v ./custom:/opt/glassfish7/custom -p 8080:8080 -ti @gf.docker.server.repository@ ``` ### Execute `asadmin` commands during Docker image build @@ -168,7 +168,7 @@ To do it, simply add `RUN instructions that run `asadmin` script with the usual File `Dockerfile`: ``` -FROM @docker.glassfish.repository@ +FROM @gf.docker.server.repository@ RUN printf "start-domain \n \ set configs.config.server-config.thread-pools.thread-pool.http-thread-pool.max-thread-pool-size=1000 \n \ @@ -188,7 +188,7 @@ stop-domain File `Dockerfile`: ``` -FROM @docker.glassfish.repository@ +FROM @gf.docker.server.repository@ COPY commands.asadmin commands.asadmin @@ -202,7 +202,7 @@ Let's try something more complicated. * To modify startup arguments for GlassFish, just add `startserv` to the command line and then add any arguments supported by the `asadmin start-domain` command. The `startserv` script is an alias to the `asadmin start-domain` command but starts GlassFish in a more efficient way that is more suitable in Docker container. For example, to start in debug mode with a custom domain, run: ```bash -docker run @docker.glassfish.repository@ startserv --debug mydomain +docker run @gf.docker.server.repository@ startserv --debug mydomain ``` * Environment variable `AS_TRACE=true` enables tracing of the GlassFish startup. It is useful when the server doesn't start without any useful logs. @@ -212,13 +212,13 @@ docker run @docker.glassfish.repository@ startserv --debug mydomain * `docker run` with `-d` starts the container as a daemon, so the shell doesn't print logs and finishes. Docker then returns the container id which you can use for further commands. ```bash -docker run -d @docker.glassfish.repository@ +docker run -d @gf.docker.server.repository@ ``` Example of running a Docker container in background, view the logs, and then stop it (with debug enabled, trace logging, and user `1000` convenient for Kubernetes ): ```bash -docker run -d -e AS_TRACE=true --user 1000 @docker.glassfish.repository@ startserv --debug=true +docker run -d -e AS_TRACE=true --user 1000 @gf.docker.server.repository@ startserv --debug=true 5a11f2fe1a9dd1569974de913a181847aa22165b5015ab20b271b08a27426e72 docker logs 5a11f2fe1a9dd1569974de913a181847aa22165b5015ab20b271b08a27426e72 @@ -242,7 +242,7 @@ If you want to run more complicated tests, the good path is to public class WelcomePageITest { @Container - private final GenericContainer server = new GenericContainer<>("@docker.glassfish.image@").withExposedPorts(8080); + private final GenericContainer server = new GenericContainer<>("@gf.docker.server.image@").withExposedPorts(8080); @Test void getRoot() throws Exception { diff --git a/src/test/java/org/glassfish/main/distributions/docker/embedded/EmbeddedDeploymentIT.java b/src/test/java/org/glassfish/main/distributions/docker/embedded/EmbeddedDeploymentIT.java index 8a08525..2911ac0 100644 --- a/src/test/java/org/glassfish/main/distributions/docker/embedded/EmbeddedDeploymentIT.java +++ b/src/test/java/org/glassfish/main/distributions/docker/embedded/EmbeddedDeploymentIT.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2025 Contributors to the Eclipse Foundation. + * Copyright (c) 2025, 2026 Contributors to the Eclipse Foundation. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v. 2.0, which is available at @@ -35,7 +35,7 @@ public class EmbeddedDeploymentIT { @SuppressWarnings({"rawtypes", "resource"}) @Container - private final GenericContainer server = new GenericContainer<>(System.getProperty("embedded.docker.glassfish.image")) + private final GenericContainer server = new GenericContainer<>(System.getProperty("gf.docker.embedded.image")) .withExposedPorts(8080) .withFileSystemBind("target/test-classes/application-test.war", "/deploy/application.war", BindMode.READ_ONLY) .waitingFor(Wait.forListeningPort().withStartupTimeout(Duration.ofMinutes(2))) diff --git a/src/test/java/org/glassfish/main/distributions/docker/server/AsadminIT.java b/src/test/java/org/glassfish/main/distributions/docker/server/AsadminIT.java index 72e40c1..c12eba1 100644 --- a/src/test/java/org/glassfish/main/distributions/docker/server/AsadminIT.java +++ b/src/test/java/org/glassfish/main/distributions/docker/server/AsadminIT.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024,2025 Contributors to the Eclipse Foundation. + * Copyright (c) 2024, 2026 Contributors to the Eclipse Foundation. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v. 2.0, which is available at @@ -22,10 +22,10 @@ import org.testcontainers.junit.jupiter.Container; import org.testcontainers.junit.jupiter.Testcontainers; +import static org.glassfish.main.distributions.docker.testutils.HttpUtilities.getServerDefaultRoot; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.stringContainsInOrder; import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.glassfish.main.distributions.docker.testutils.HttpUtilities.getServerDefaultRoot; /** * @@ -35,8 +35,8 @@ public class AsadminIT { @SuppressWarnings({"rawtypes", "resource"}) @Container - private final GenericContainer server = new GenericContainer<>(System.getProperty("server.docker.glassfish.image")) - .withCommand("asadmin start-domain").withExposedPorts(8080) + private final GenericContainer server = new GenericContainer<>(System.getProperty("gf.docker.server.image")) + .withCommand("asadmin", "start-domain").withExposedPorts(8080) .withLogConsumer(o -> System.err.print("GF: " + o.getUtf8String())); @Test diff --git a/src/test/java/org/glassfish/main/distributions/docker/server/ChangePasswordsIT.java b/src/test/java/org/glassfish/main/distributions/docker/server/ChangePasswordsIT.java index e4ff885..c2015e4 100644 --- a/src/test/java/org/glassfish/main/distributions/docker/server/ChangePasswordsIT.java +++ b/src/test/java/org/glassfish/main/distributions/docker/server/ChangePasswordsIT.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2025 Contributors to the Eclipse Foundation + * Copyright (c) 2025, 2026 Contributors to the Eclipse Foundation * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v. 2.0, which is available at @@ -16,9 +16,11 @@ package org.glassfish.main.distributions.docker.server; import java.net.http.HttpResponse; +import java.util.UUID; import org.junit.jupiter.api.Test; import org.testcontainers.containers.GenericContainer; +import org.testcontainers.containers.Container.ExecResult; import org.testcontainers.junit.jupiter.Container; import org.testcontainers.junit.jupiter.Testcontainers; @@ -35,13 +37,18 @@ @Testcontainers public class ChangePasswordsIT { + private static final String ADMIN_PASSWORD = UUID.randomUUID().toString(); + @SuppressWarnings({"rawtypes", "resource"}) @Container - private final GenericContainer server = new GenericContainer<>(System.getProperty("server.docker.glassfish.image")) - .withExposedPorts(8080, 4848) - .withEnv("AS_ADMIN_MASTERPASSWORD", "mymasterpassword") - .withEnv("AS_ADMIN_PASSWORD", "myadminpassword") - .withLogConsumer(o -> System.err.print("GF: " + o.getUtf8String())); + private final GenericContainer server = new GenericContainer<>(System.getProperty("gf.docker.server.image")) + .withExposedPorts(8080, 4848) + .withEnv("AS_ADMIN_MASTERPASSWORD", "mymasterpassword") + .withEnv("JAVA_OPTIONS", + "-Djavax.net.ssl.trustStore=/opt/glassfish7/glassfish/domains/domain1/config/cacerts.jks " + + "-Djavax.net.ssl.trustStorePassword=changeit") + .withEnv("AS_ADMIN_PASSWORD", ADMIN_PASSWORD) + .withLogConsumer(o -> System.err.print("GF: " + o.getUtf8String())); @Test void rootResourceGivesOkWithDefaultResponse() throws Exception { @@ -51,10 +58,16 @@ void rootResourceGivesOkWithDefaultResponse() throws Exception { } @Test - void customAdminPassword() throws Exception { + void customAdminPassword_HTTP() throws Exception { final HttpResponse adminResourceResponse = getAdminResource(server, "/management/domain.json", - new UserPassword("admin", "myadminpassword")); + new UserPassword("admin", ADMIN_PASSWORD)); assertEquals(200, adminResourceResponse.statusCode(), "Response status code"); } + @Test + void customAdminPassword_asadmin() throws Exception { + ExecResult result = server.execInContainer("asadmin", "--passwordfile", "/password.txt", "get", "*"); + assertEquals(0, result.getExitCode()); + assertThat(result.getStderr(), result.getStdout(), stringContainsInOrder("servers.server.server.name=server")); + } } diff --git a/src/test/java/org/glassfish/main/distributions/docker/server/DefaultIT.java b/src/test/java/org/glassfish/main/distributions/docker/server/DefaultIT.java index dd0737d..b892583 100644 --- a/src/test/java/org/glassfish/main/distributions/docker/server/DefaultIT.java +++ b/src/test/java/org/glassfish/main/distributions/docker/server/DefaultIT.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2025 Contributors to the Eclipse Foundation. + * Copyright (c) 2025, 2026 Contributors to the Eclipse Foundation. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v. 2.0, which is available at @@ -33,7 +33,7 @@ public class DefaultIT { @SuppressWarnings({"rawtypes", "resource"}) @Container - private final GenericContainer server = new GenericContainer<>(System.getProperty("server.docker.glassfish.image")) + private final GenericContainer server = new GenericContainer<>(System.getProperty("gf.docker.server.image")) .withExposedPorts(8080) .withLogConsumer(o -> System.err.print("GF: " + o.getUtf8String())); diff --git a/src/test/java/org/glassfish/main/distributions/docker/server/StartAndDeployIT.java b/src/test/java/org/glassfish/main/distributions/docker/server/StartAndDeployIT.java index babc1f1..b130ba3 100644 --- a/src/test/java/org/glassfish/main/distributions/docker/server/StartAndDeployIT.java +++ b/src/test/java/org/glassfish/main/distributions/docker/server/StartAndDeployIT.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024,2025 Contributors to the Eclipse Foundation. + * Copyright (c) 2024, 2026 Contributors to the Eclipse Foundation. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v. 2.0, which is available at @@ -36,7 +36,7 @@ public class StartAndDeployIT { @SuppressWarnings({"rawtypes", "resource"}) @Container - private final GenericContainer server = new GenericContainer<>(System.getProperty("server.docker.glassfish.image")) + private final GenericContainer server = new GenericContainer<>(System.getProperty("gf.docker.server.image")) .withCommand("startserv") .withExposedPorts(8080) .withFileSystemBind("target/test-classes/application-test.war", "/deploy/application-test.war", BindMode.READ_ONLY) diff --git a/src/test/java/org/glassfish/main/distributions/docker/testutils/HttpUtilities.java b/src/test/java/org/glassfish/main/distributions/docker/testutils/HttpUtilities.java index c514881..1fa8bfe 100644 --- a/src/test/java/org/glassfish/main/distributions/docker/testutils/HttpUtilities.java +++ b/src/test/java/org/glassfish/main/distributions/docker/testutils/HttpUtilities.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2025 Contributors to the Eclipse Foundation + * Copyright (c) 2025, 2026 Contributors to the Eclipse Foundation * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v. 2.0, which is available at @@ -19,7 +19,6 @@ import java.net.http.HttpClient; import java.net.http.HttpRequest; import java.net.http.HttpResponse; -import java.nio.charset.StandardCharsets; import java.security.KeyManagementException; import java.security.NoSuchAlgorithmException; import java.security.SecureRandom; @@ -34,6 +33,7 @@ import org.testcontainers.containers.GenericContainer; import static java.net.http.HttpResponse.BodyHandlers.ofString; +import static java.nio.charset.StandardCharsets.UTF_8; import static java.time.Duration.ofSeconds; /** @@ -42,6 +42,23 @@ */ public final class HttpUtilities { + private static final TrustManager[] NAIVE_TRUST_MANAGERS = new TrustManager[] {new X509TrustManager() { + + @Override + public java.security.cert.X509Certificate[] getAcceptedIssuers() { + return null; + } + + @Override + public void checkClientTrusted(java.security.cert.X509Certificate[] certs, String authType) { + } + + @Override + public void checkServerTrusted(java.security.cert.X509Certificate[] certs, String authType) { + } + }}; + + private HttpUtilities() { } @@ -49,7 +66,7 @@ public static HttpResponse getServerDefaultRoot(GenericContainer server) URI uri = URI.create("http://localhost:" + server.getMappedPort(8080) + "/"); try (HttpClient client = newInsecureHttpClient()) { final HttpRequest request = HttpRequest.newBuilder(uri).build(); - return client.send(request, ofString(StandardCharsets.UTF_8)); + return client.send(request, ofString(UTF_8)); } } @@ -57,7 +74,7 @@ public static HttpResponse getEmbeddedDefaultRoot(GenericContainer serve URI uri = URI.create("http://localhost:" + server.getMappedPort(8080) + "/"); try (HttpClient client = newInsecureHttpClient()) { final HttpRequest request = HttpRequest.newBuilder(uri).build(); - return client.send(request, ofString(StandardCharsets.UTF_8)); + return client.send(request, ofString(UTF_8)); } } @@ -71,7 +88,7 @@ public static HttpResponse getApplication(GenericContainer server, Strin while ((System.currentTimeMillis() - startTime) < Duration.ofSeconds(30).toMillis()) { try (HttpClient client = newInsecureHttpClient()) { final HttpRequest request = HttpRequest.newBuilder(uri).build(); - response = client.send(request, ofString(StandardCharsets.UTF_8)); + response = client.send(request, ofString(UTF_8)); if (response.statusCode() == 200) { return response; @@ -90,13 +107,13 @@ public static HttpResponse getAdminResource(GenericContainer server, Str final HttpRequest request = HttpRequest.newBuilder(uri) .setHeader("Authorization", basicAuthValue(userPass)) .build(); - return client.send(request, ofString(StandardCharsets.UTF_8)); + return client.send(request, ofString(UTF_8)); } } private static HttpClient newInsecureHttpClient() throws KeyManagementException, NoSuchAlgorithmException { SSLContext sslContext = SSLContext.getInstance("TLS"); - sslContext.init(null, trustAllCerts, new SecureRandom()); + sslContext.init(null, NAIVE_TRUST_MANAGERS, new SecureRandom()); HttpClient client = HttpClient.newBuilder() .sslContext(sslContext) .build(); @@ -108,24 +125,4 @@ private static String basicAuthValue(UserPassword userPass) { String basicAuth = "Basic " + new String(Base64.getEncoder().encode(userCredentials.getBytes())); return basicAuth; } - - private static final TrustManager[] trustAllCerts = new TrustManager[]{ - new X509TrustManager() { - @Override - public java.security.cert.X509Certificate[] getAcceptedIssuers() { - return null; - } - - @Override - public void checkClientTrusted( - java.security.cert.X509Certificate[] certs, String authType) { - } - - @Override - public void checkServerTrusted( - java.security.cert.X509Certificate[] certs, String authType) { - } - } - }; - }