github.com/qsunny/k8s@v0.0.0-20220101153623-e6dca256d5bf/examples-master/staging/javaweb-tomcat-sidecar/README.md (about)

     1  ## Java Web Application with Tomcat and Init Container
     2  
     3  The following document describes the deployment of a Java Web application using Tomcat. Instead of packaging `war` file inside the Tomcat image or mount the `war` as a volume, we use an [init-container](https://kubernetes.io/docs/concepts/workloads/pods/init-containers/) as `war` file provider.
     4  
     5  ### Prerequisites
     6  
     7  https://github.com/kubernetes/kubernetes/blob/master/docs/user-guide/prereqs.md
     8  
     9  ### Overview
    10  
    11  This sidecar mode brings a new workflow for Java users:
    12  
    13  ![](workflow.png?raw=true "Workflow")
    14  
    15  As you can see, user can create a `sample:v2` container as an `initContainers` object to "provide" war file to Tomcat by copying it to the shared `emptyDir` volume. And Pod will make sure the two containers compose an "atomic" scheduling unit, which is perfect for this case. Thus, your application version management will be totally separated from web server management.
    16  
    17  By using an init-container the `tomcat` container is assured of the `war` file existing before start up as the pod will not start normal containers until all init-containers have completed successfully.
    18  
    19  For example, if you are going to change the configurations of your Tomcat:
    20  
    21  ```console
    22  $ docker exec -it <tomcat_container_id> /bin/bash
    23  # make some change, and then commit it to a new image
    24  $ docker commit <tomcat_container_id> mytomcat:7.0-dev
    25  ```
    26  
    27  Done! The new Tomcat image **will not** mess up with your `sample.war` file. You can re-use your tomcat image with lots of different war container images for lots of different apps without having to build lots of different images.
    28  
    29  Also this means that rolling out a new Tomcat to patch security or whatever else, doesn't require rebuilding N different images.
    30  
    31  **Why not put my `sample.war` in a host dir and mount it to tomcat container?**
    32  
    33  You have to **manage the volumes** in this case, for example, when you restart or scale the pod on another node, your contents is not ready on that host.
    34  
    35  Generally, we have to set up a distributed file system (NFS at least) volume to solve this (if we do not have GCE PD volume). But this is generally unnecessary.
    36  
    37  ### How To Set this Up
    38  
    39  In Kubernetes a [_Pod_](https://kubernetes.io/docs/user-guide/pods.md) is the smallest deployable unit that can be created, scheduled, and managed. It's a collocated group of containers that share an IP and storage volume.
    40  
    41  Here is the config [javaweb.yaml](javaweb.yaml) for Java Web pod:
    42  
    43  NOTE: you should define `war` init-container **first** as it is the "provider".
    44  
    45  <!-- BEGIN MUNGE: javaweb.yaml -->
    46  
    47  ```yaml
    48  apiVersion: v1
    49  kind: Pod
    50  metadata:
    51    name: javaweb
    52  spec:
    53    initContainers:
    54      - image: resouer/sample:v1
    55        name: war
    56        volumeMounts:
    57          - mountPath: /app
    58            name: app-volume
    59    containers:
    60      - image: resouer/mytomcat:7.0
    61        name: tomcat
    62        command: ["sh", "-c", "/root/apache-tomcat-7.0.42-v2/bin/start.sh"]
    63        volumeMounts:
    64          - mountPath: /root/apache-tomcat-7.0.42-v2/webapps
    65            name: app-volume
    66        ports:
    67          - containerPort: 8080
    68            hostPort: 8001
    69    volumes:
    70      - name: app-volume
    71        emptyDir: {}
    72  ```
    73  
    74  <!-- END MUNGE: EXAMPLE -->
    75  
    76  The only magic here is the `resouer/sample:v1` image:
    77  
    78  ```
    79  FROM busybox:latest
    80  ADD sample.war sample.war
    81  CMD "sh" "mv.sh"
    82  ```
    83  
    84  And the contents of `mv.sh` is:
    85  
    86  ```sh
    87  cp /sample.war /app
    88  tail -f /dev/null
    89  ```
    90  
    91  #### Explanation
    92  
    93  1. 'war' container only contains the `war` file of your app
    94  2. 'war' container's CMD tries to copy `sample.war` to the `emptyDir` volume path
    95  3. The last line of `tail -f` is just used to hold the container, as Replication Controller does not support one-off task
    96  4. 'tomcat' container will load the `sample.war` from volume path
    97  
    98  What's more, if you don't want to enclose a build-in `mv.sh` script in the `war` container, you can use Pod's `command` to do the copy work, here's a example [javaweb-2.yaml](javaweb-2.yaml):
    99  
   100  <!-- BEGIN MUNGE: javaweb-2.yaml -->
   101  
   102  ```yaml
   103  apiVersion: v1
   104  kind: Pod
   105  metadata:
   106    name: javaweb-2
   107  spec:
   108    initContainers:
   109    - image: resouer/sample:v2
   110      name: war
   111        command:
   112          - "cp"
   113          - "/sample.war"
   114          - "/app"
   115      volumeMounts:
   116      - mountPath: /app
   117        name: app-volume
   118    containers:
   119    - image: resouer/mytomcat:7.0
   120      name: tomcat
   121      command: ["sh","-c","/root/apache-tomcat-7.0.42-v2/bin/start.sh"]
   122      volumeMounts:
   123      - mountPath: /root/apache-tomcat-7.0.42-v2/webapps
   124        name: app-volume
   125      ports:
   126      - containerPort: 8080
   127        hostPort: 8001
   128    volumes:
   129    - name: app-volume
   130      emptyDir: {}
   131  ```
   132  
   133  <!-- END MUNGE: EXAMPLE -->
   134  
   135  And the `resouer/sample:v2` Dockerfile is quite simple:
   136  
   137  ```
   138  FROM busybox:latest
   139  ADD sample.war sample.war
   140  CMD "tail" "-f" "/dev/null"
   141  ```
   142  
   143  #### Explanation
   144  
   145  1. 'war' container only contains the `war` file of your app
   146  2. 'war' container's CMD uses `tail -f` to hold the container, nothing more
   147  3. The `command` will do `cp` after the `war` container is started
   148  4. Again 'tomcat' container will load the `sample.war` from volume path
   149  
   150  Done! Now your `war` container contains nothing except `sample.war`, clean enough.
   151  
   152  ### Test It Out
   153  
   154  Create the Java web pod:
   155  
   156  ```console
   157  $ kubectl create -f examples/javaweb-tomcat-sidecar/javaweb-2.yaml
   158  ```
   159  
   160  Check status of the pod:
   161  
   162  ```console
   163  $ kubectl get -w po
   164  NAME        READY     STATUS    RESTARTS   AGE
   165  javaweb-2   2/2       Running   0         7s
   166  ```
   167  
   168  Wait for the status to `0/1` and `Running`. Then you can visit "Hello, World" page on `http://localhost:8001/sample/index.html`
   169  
   170  You can also test `javaweb.yaml` in the same way.
   171  
   172  ### Delete Resources
   173  
   174  All resources created in this application can be deleted:
   175  
   176  ```console
   177  $ kubectl delete -f examples/javaweb-tomcat-sidecar/javaweb-2.yaml
   178  ```
   179  
   180  <!-- BEGIN MUNGE: GENERATED_ANALYTICS -->
   181  
   182  [![Analytics](https://kubernetes-site.appspot.com/UA-36037335-10/GitHub/examples/javaweb-tomcat-sidecar/README.md?pixel)]()
   183  
   184  <!-- END MUNGE: GENERATED_ANALYTICS -->