0

I need to provide a POC as argument for the migration of workflows in my current job. Currently we do this:

  1. People code on Netbeans
  2. People click on build on netbeans
  3. Deploy locally
  4. Apply code changes
  5. Netbeans rebuilds and redeploy the code.

Things to know:

  • It seems tomcat detects when a new WAR is put in the directory and hot-deploys it;
  • What I aim to automate is not the hot-deploy(since this is already a tomcat feature), but the build process;
  • We are using Maven to build the project.
  • I'm using docker-compose to get everything up in one single specification.

So far I was able to containerize the Postgres database, the PGAdmin we use and the initial build of the application using a multi-stage Dockerfile.

Tomcat app Dockerfile

FROM maven AS buildserver

ADD . /usr/src/mymaven/
WORKDIR /usr/src/mymaven
# build the project
RUN mvn -f pom.xml clean package -DskipTests

FROM tomcat:latest
COPY conf-tomcat/tomcat-users.xml /usr/local/tomcat/conf/
COPY conf-tomcat/server.xml /usr/local/tomcat/conf/
COPY conf-tomcat/context.xml /usr/local/tomcat/webapps/manager/META-INF/
# Copy the built war file into webapps folder of tomcat container
COPY --from=buildserver /usr/src/mymaven/target/*.war /usr/local/tomcat/webapps

What I am having trouble with is triggering the rebuild when there's code changes (imitating what netbeans does). I can't find in either maven's or netbeans documentation how that detection and triggering works.

I am using volumes to map the app source directory to the container in hopes that it would just work, but I was wrong.

My docker-compose.yml is as follows:

version: '3'
services:
  pgadmin:
    container_name: pgadmin
    image: dpage/pgadmin4
    env_file:
      - ../db-postgres/pgadmin/pgadmin.env
    depends_on:
      - pg-dev
    networks:
      - dev-network
    volumes:
      - pgadmin-data:/var/lib/pgadmin
    ports:
      - "88:80"
  pg-dev:
    container_name: pg-dev
    image: pg-dev:latest
    env_file:
      - ../db-postgres/db-dev/pg-dev.env
    volumes:
      - pg-data:/var/lib/postgresql/data
    networks:
      - dev-network
    ports:
      - "5433:5432"
  app:
    container_name: app
    build: .
    volumes:
      - app-src:/usr/src/mymaven
      - artifacts:/usr/src/mymaven/target
      - maven-repo:/root/.m2
    networks:
      - dev-network
    ports:
      - "8888:8080"
    depends_on:
      - pg-dev
volumes:
  maven-repo:
    driver: local
    driver_opts:
      type: bind
      device: $HOME/.m2
      o: bind
  app-src:
    driver: local
    driver_opts:
      type: bind
      device: .
      o: bind
  artifacts:
    driver: local
    driver_opts:
      type: bind
      device: target/
      o: bind
  pg-data:
  pgadmin-data:
networks:
  dev-network:

Any help in coming up with a solution for this is appreciated, as well as any general advice in how to make this workflow/build improve.

UPDATE

I came up with somewhat of a work around, but now I am having problem testing it.

I defined a maven container to work as a build server:

FROM maven

ADD . /usr/src/mymaven/
WORKDIR /usr/src/mymaven
RUN apt update && apt install entr -y
# build the project
RUN mvn -f pom.xml clean package -DskipTests

and now I am defining the entrypoint on the docker-compose.yml:

...
 buildserver:
    container_name: buildserver
    build:
      context: .
      dockerfile: maven-builder.Dockerfile
    volumes:
      - app-src:/usr/src/mymaven
      - maven-repo:/root/.m2
      - artifacts:/usr/src/mymaven/target
    networks:
      - dev-network
    entrypoint: sh -c 'find src/ | entr mvn -f pom.xml clean package -DskipTests --batch-mode'
...

But now I am getting an error message when this container gets up:

find: ‘src/’: No such file or directory
entr: No regular files to watch

Which is weird to me as I successfully build the project in the first run, but the entry-point seems to be failing.

Clarification: What I am being asked is come up with a workflow that removes the need to use the deploy from Netbeans (they want everything automatic). I looked around for a Jenkins workflow, but could not really find a way to achieve the desired results.

inblank
  • 396
  • 1
  • 8
  • 26
  • You should be using a CI/CD framework such as Jenkins/Bamboo/TeamCity. – K.Nicholas Jul 23 '19 at 20:22
  • That is what I intend as the next step. I am educating people in writing tests now, so I don't know if I could come up with a CI/CD solution. Also, this is meant to be at first a development environment, and if it works we will move it to production. – inblank Jul 23 '19 at 20:32
  • `I can't find in either maven's or netbeans documentation how that detection and triggering works.` This is not the title of your question. Maven doesn't detect code changes. If you want to educate I think it would be better to run Jenkins in a container or something and get a simple example of that working. It's easy enough. – K.Nicholas Jul 23 '19 at 20:36
  • what if you used `docker cp` to copy the war file into a running tomcat container instead of using volume mapping? will that trigger the hot-deploy? For me to keep that hot-deploy feature means keeping it fast as well, so re-building the image of the container and then restarting the active one would be slow sort of speak – ahasbini Jul 23 '19 at 20:39
  • @ahasbini yes it does. I just need to find a way to automatically rebuild the WAR when there're changes on the code (my main point and question). I'll edit the question title to express that more clearly – inblank Jul 23 '19 at 20:48

1 Answers1

0

According to the Netbeans docs, you can bind Maven goals to IDE actions (http://wiki.netbeans.org/MavenBestPractices section Binding Maven goals to IDE actions):

It's possible to customize the default Maven goal to IDE Action binding from the project's customizer. Right click on the project node and select "Properties" or use the File/Project Properties main menu item to invoke the Project properties dialog. On the left hand side, select the panel named "Actions". The panel lists all available default project actions that can be mapped. When selecting one from the list the textfields in the bottom allow to change the values.

It looks to me that you should bind the Build Project Netbeans action to a specific Maven goal. From this point, it is up to you to come up with a creative solution. You could explore the Maven Exec plugin capabilities and run custom commands during the build proccess (check I want to execute shell commands from Maven's pom.xml). For instance, it should be possible to copy the .war file from target folder to wherever you want on the filesystem, or even execute scripts inside the running container.

PS: It looks like you are trying to do something quite odd, but I'll assume here it makes sense to you solving this somehow.

Rafael Odon
  • 1,211
  • 14
  • 20
  • Thanks for the input. Indeed it is something odd. The goal is to replace our current dev setup, since 15 new interns are joining and our setup is a pain in dependencies and tooling. I proposed we use docker and docker-compose to setup the environment so nothing is needed besides docker and an editor(like VScode or vim) and was asked to come up with a solution after a 40 minutes presentation in the advantages of using it. – inblank Jul 23 '19 at 22:15