Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Sample scripts to create an image with an applicaiton running on a ma… #401

Merged
merged 9 commits into from
Jul 20, 2017
61 changes: 61 additions & 0 deletions OracleWebLogic/samples/12212-msiserver/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
# LICENSE CDDL 1.0 + GPL 2.0
#
# Copyright (c) 2017 Oracle and/or its affiliates. All rights reserved.
#
# ORACLE DOCKERFILES PROJECT
# --------------------------
# This Dockerfile extends the Oracle WebLogic image by creating an domain on which
# a managed server can be launched in Managed Server Independence (MSI) mode
#
# REQUIRED FILES TO BUILD THIS IMAGE
# ----------------------------------
#
# HOW TO BUILD THIS IMAGE
# -----------------------
# Run:
# $ sudo docker build -t 12212-msiserver .
#

# Pull base image
# ---------------
FROM oracle/weblogic:12.2.1.2-developer

# Maintainer
# ----------
MAINTAINER Aseem Bajaj <aseem.bajaj@oracle.com>

# Arguments
# ---------
ARG number_of_ms=10
ARG domains_dir=wlserver/samples/domains
ARG domain_name=msi-sample
ARG ms_name_prefix=ms
ARG ms_port=8011
ARG prod_or_dev=dev

# Environment variables required for this build (do NOT change)
# -------------------------------------------------------------
ENV MW_HOME="$ORACLE_HOME" \
PATH="$ORACLE_HOME/wlserver/server/bin:$ORACLE_HOME/wlserver/../oracle_common/modules/org.apache.ant_1.9.2/bin:$JAVA_HOME/jre/bin:$JAVA_HOME/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:$ORACLE_HOME/oracle_common/common/bin:$ORACLE_HOME/wlserver/common/bin:$ORACLE_HOME/user_projects/domains/medrec/bin:$ORACLE_HOME/wlserver/samples/server/medrec/:$ORACLE_HOME/wlserver/samples/server/:$ORACLE_HOME/wlserver/../oracle_common/modules/org.apache.maven_3.2.5/bin" \
NUMBER_OF_MS=$number_of_ms \
DOMAINS_DIR=$ORACLE_HOME/$domains_dir \
DOMAIN_NAME=$domain_name \
MS_NAME_PREFIX=$ms_name_prefix \
DEFAULT_MS_NAME=${ms_name_prefix}1 \
MS_PORT=$ms_port \
PROD_OR_DEV=$prod_or_dev

# Copy scripts
# --------------------------------
USER oracle
COPY container-scripts/* /u01/oracle/

# Default directory creation, Admin Server boot
# ---------------------------------------------
RUN . $ORACLE_HOME/wlserver/server/bin/setWLSEnv.sh && \
cd /u01/oracle && \
./provision-domain-for-msi.sh $DOMAIN_NAME $ORACLE_HOME/wlserver/common/templates/wls/wls.jar $DOMAINS_DIR weblogic weblogic1 8001 $DEFAULT_MS_NAME $MS_PORT $PROD_OR_DEV $NUMBER_OF_MS $MS_NAME_PREFIX

EXPOSE $MS_PORT
WORKDIR $DOMAINS_DIR/$DOMAIN_NAME
ENTRYPOINT ["/u01/oracle/launcher.sh"]
49 changes: 49 additions & 0 deletions OracleWebLogic/samples/12212-msiserver/Dockerfile.addapp
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
# LICENSE CDDL 1.0 + GPL 2.0
#
# Copyright (c) 2017 Oracle and/or its affiliates. All rights reserved.
#
# ORACLE DOCKERFILES PROJECT
# --------------------------
# This Dockerfile extends the Oracle WebLogic MSI server image by adding app
# bits to the image and recording it in domain configuration
#
# REQUIRED FILES TO BUILD THIS IMAGE
# ----------------------------------
#
# HOW TO BUILD THIS IMAGE
# -----------------------
# Run the following command for the sample application included in this directory. The name and source identify
# the name of the applciation to be used and the application source. simple_file identified the simple file name
# that will be used to copy the source file on the image. It can be the same as the last element of application
# source
# $ sudo docker build -t 12212-summercamps-msiserver -f Dockerfile.addapp --build-arg name=summercamps --build-arg source=apps/summercamps.ear --build-arg simple_filename=summercamps.ear .
#

# Pull base image
# ---------------
FROM 12212-msiserver:latest

# Maintainer
# ----------
MAINTAINER Aseem Bajaj <aseem.bajaj@oracle.com>

# Arguments
# ---------
ARG name=summercamps
ARG source=apps/summercamps.ear
ARG simple_filename=summercamps.ear

# Environment variables required for this build (do NOT change)
# -------------------------------------------------------------
ENV MW_HOME="$ORACLE_HOME" \
PATH="$ORACLE_HOME/wlserver/server/bin:$ORACLE_HOME/wlserver/../oracle_common/modules/org.apache.ant_1.9.2/bin:$JAVA_HOME/jre/bin:$JAVA_HOME/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:$ORACLE_HOME/oracle_common/common/bin:$ORACLE_HOME/wlserver/common/bin:$ORACLE_HOME/user_projects/domains/medrec/bin:$ORACLE_HOME/wlserver/samples/server/medrec/:$ORACLE_HOME/wlserver/samples/server/:$ORACLE_HOME/wlserver/../oracle_common/modules/org.apache.maven_3.2.5/bin"

# Copy scripts
# --------------------------------
USER oracle
COPY ${source} /u01/apps/${simple_filename}

# WLST offline use to update domain configuration
# ---------------------------------------------
RUN . $ORACLE_HOME/wlserver/server/bin/setWLSEnv.sh && \
java weblogic.WLST /u01/oracle/add-app-to-domain.py $DOMAINS_DIR/$DOMAIN_NAME $NUMBER_OF_MS $name /u01/apps/${simple_filename} $MS_NAME_PREFIX
160 changes: 160 additions & 0 deletions OracleWebLogic/samples/12212-msiserver/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
Example of docker images with WebLogic server in MSI Mode
=========================================================
This Dockerfile extends the Oracle WebLogic image by creating a domain that configures a managed
server in MSI mode (or Managed Server Independence mode). In this mode, a managed server can run
without the need of an admin server. Such a managed server is not driven by admin server for
configuration or deployment changes. However, it can handle all configuration and deploymnets
Copy link
Member

Choose a reason for hiding this comment

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

Typo: should be "deployments"

already in config.xml like any other managed server. For use cases where the managed server does
not need to be updated for configuration or deployments, this image can be used by itself without
running a admin server or node manager

How to build and run the base image
-----------------------------------
First make sure you have built **oracle/weblogic:12.2.1.2-developer**.

Next, to build the base msi image, run:

$ docker build -t 12212-msiserver .

Finally, to start the Managed Server in MSI mode, run:

$ docker run -d -p 8011:8011 12212-msiserver

Connect to this container instance. You'll notice that the managed server is running from a domain
located at /u01/msi-server. Under the servers directory, you'll notice a server name that seems
randomly generated. It is of pattern ms[0-9]*. Say that your generated container id is cf579fd131fc
and you find that the random managed server name is ms3. You can verify the server is in MSI mode
by searching for a catalog message BEA-150018

$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
cf579fd131fc 12212-msiserver "/u01/oracle/launc..." 2 minutes ago Up 2 minutes 0.0.0.0:8011->8011/tcp vigilant_volhard

$ docker exec -it cf579fd131fc bash
Copy link
Member

Choose a reason for hiding this comment

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

You should never need to exec bash into a container. If you need the user to know something, that log file should be sent to stdout at runtime so that the user can use docker logs (or any of the logging drivers) to get the output.


$ cat servers/ms3/logs/ms3.log | grep BEA-150018
Copy link
Member

Choose a reason for hiding this comment

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

As above. You should be tailing this log to stdout by default. Take a look at the Database and other Dockerfiles for examples of this.

####<May 16, 2017, 6:30:09,993 PM GMT> <Info> <Configuration Management> <cf579fd131fc> <> <Thread-11> <> <> <> <1494959409993> <[severity-value: 64] [partition-id: 0] [partition-name: DOMAIN] > <BEA-150018> <This server is being started in Managed Server independence mode in the absence of the Administration Server.>

Also note that the this server does not have a publicly accessible URL since no application is
deployed to it yet. When additional images are created by adding application(s) to this base image
the same command (as above) may be used to launch the server and accessed using the URL
http://localhost:8011/<relevant-context-root>

Randomly generated managed server name can be overridden using build arguments or runtime variables.

**Build Argument ms_name_prefix**
This argument may be used to alter the prefix of managed server name, and a random
number prefix is appended to it. For example, the following command may be used to
run a managed with a name managedServer<RandomNumber>

docker build -t 12212-msiserver --build-arg ms_name_prefix=managedServer .

**Build Argument number_of_ms**
By default, this image comes configured with 10 managed servers, ms1 to ms10. However, the image
can be built with configurable number of managed servers using NUMBER_OF_MS argument

docker build -t 12212-msiserver --build-arg number_of_ms=15 .

**Other build arguments**
* domain_name may be used to identify the name of generated domain that gets packed into MSI image. Default value msi-sample
* domains_dir may be used identify the directory under $ORACLE_HOME where the domain home directory is created. Default value wlserver/samples/domains
* ms_port may be used to configure port of the managed server, default is 8011
* prod_or_dev may be used to identify whether server is started in production or development mode. Defaults to "dev" for development mode.

**Runtime Argument MS_NAME**
This argument may be used to completely override the managed server name.
For example, the following command may be used to run a managed server with name ms1

docker run --name msiserver --env MS_NAME=managedServer1 12212-msiserver

How to use the base image to add application
--------------------------------------------
To build, run:
$ docker build -t 12212-summercamps-msiserver -f Dockerfile.addapp --build-arg name=summercamps --build-arg source=apps/summercamps.ear --build-arg simple_filename=summercamps.ear .

Dockerfile.addapp adds an app called summercamps.ear targeted to the cluster that
the managed server is a part of

To start the Managed Server in MSI mode with this app, run:

$ docker run -d -p 8011:8011 12212-summercamps-msiserver

summercamps app will now be accessible at

http://localhost:8011/

As with the base image, you can still override managed server name and cluster name
**Build arguments**
Three build arguments may be used to customize the image to include an application of user
choice. By default, the build arguments point to an example application included in this
sample. The "name" argument helps identify the name of deployment, while the "source"
argument helps identify the source of the application. The source is copied into the image.
So "simple_filename" helps identify the name of the file where the source is copied to

Using swarm service creation with this image
Copy link
Member

Choose a reason for hiding this comment

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

Your instructions should assume that user has a local registry and Swarm running. You don't have to provide documentation on how to do that. You can provide links to the registry and Swarm documentation though.

Copy link
Member Author

Choose a reason for hiding this comment

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

Hi @Djelibeybi

Thanks for the inputs. I have incorporated all your feedback. Please take a look.

--------------------------------------------
The image called 12212-summercamps-msiserver can be used for Docker service creation
to scale out to multiple replicas. docker service creation can only be done
Copy link
Member

Choose a reason for hiding this comment

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

Typo: "docker" should be "Docker"

using an image from a docker registry. If you don't have publishing rights to a docker
registry you can start one locally. More details can be found here
https://docs.docker.com/registry/deploying/

Here are the three steps you'll need to start, use and push to your local registry.
Copy link
Member

Choose a reason for hiding this comment

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

Don't provide documentation on how to run a registry, because this will get out of date. You already point to the Docker docs, that's sufficient.

Also, a registry is not required for a service, if you have the same image on all the hosts in the Swarm. It's just that the simplest way for that to happen is to use a local registry. :)

If you do have push rights to an existing docker registry, you can skip to the third
step

1. Start the registry
docker run -d -p 5000:5000 --restart=always --name registry registry:2

2. Change docker preferences to add this local registry to your list of insecure registries
{
"insecure-registries" : [
"localhost:5000"
]
}

3. Push to the local registry
docker tag 12212-summercamps-msiserver localhost:5000/12212-summercamps-msiserver
docker push localhost:5000/12212-summercamps-msiserver

Now that your image is published to the registry, start by joining swarm, either a swarm
Copy link
Member

Choose a reason for hiding this comment

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

Please do not provide instructions on how to use Swarm here either. Rather just point to the Swarm documentation.

leader or as a swarm worker

$ docker swarm init

Next create a service using a command like this

$ docker service create --name city_activity_guide -p 8011:8011 --hostname "msihost" --host "msihost:127.0.0.1" --env "MS_NAME=ms{{.Task.Slot}}" --replicas 3 localhost:5000/12212-summercamps-msiserver:latest

The following experimental feature in 17.03.1-ce is useful for examining logs for all
service replicas
$ docker service logs city_activity_guide

In the above example, a service is created with 3 replicas. We use templatized --env
to pass in a custom managed server name to the service. In this example a built-in
load balancer exposes port 8011. Accessing the URL will send the request to the three
replicas based on default load balancing algorithm. You should be able to see managed
server name printed in response:

$ curl http://localhost:8011/

If you use a browser, the session will be sticky. And you can see a session
variable called "Sports camps" being updated

You can scale the service using another service command. For example, you can scale up to
5 replicas using the following command

docker service scale city_activity_guide=5

Or you can scale down to say one replica

docker service scale city_activity_guide=1

If you are testing on different browser instances and you can verify that each browser is
hitting a different replica, you'll notice them all move to the same replica when you scale
down to 1

You can shutdown the service using
docker service rm city_activity_guide

Copyright (c) 2017 Oracle and/or its affiliates. All rights reserved.
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<application version="5">
<module>
<web>
<context-root>/</context-root>
<web-uri>registration.war</web-uri>
</web>
</module>
</application>
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<weblogic-web-app xmlns="http://xmlns.oracle.com/weblogic/weblogic-web-app">
<description> weblogic.xml for memory persistence </description>
<session-descriptor>
<persistent-store-type>replicated_if_clustered</persistent-store-type>
</session-descriptor>
</weblogic-web-app>
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<%@ page import="java.net.InetAddress" %>
<%@ page import="javax.servlet.http.Cookie" %>
<html>
<title>Account Profile</title>
<body>
<h3>Account Profile</h3>
<%
Object attr = session.getAttribute("counter");
int counter = (attr != null ? ((Integer) attr) : 0);
counter++;
session.setAttribute("counter", counter);
out.println("Sports camps signed up for " + counter + "<br>");
%>
<hr>
<small>
<%
out.println("Managed Server Name " + System.getProperty("weblogic.Name") + "<br>");
/*
out.println("Hostname " + InetAddress.getLocalHost().getHostName() + "<br>");
Cookie[] cookies = request.getCookies();
String jSessionId = null;

if (cookies != null) {
for (int i = 0; i < cookies.length; i++) {
if ("JSESSIONID".equals(cookies[i].getName())) {
jSessionId = cookies[i].getValue();
}
}
}
out.println("JSESSIONID is " + jSessionId);
*/
%>
</small>
</body>
</html>
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
domain_path = sys.argv[1]
number_of_ms = int(sys.argv[2])
app_name = sys.argv[3]
app_location = sys.argv[4]
ms_name_prefix = sys.argv[5]

print('domain_path : [%s]' % domain_path);
print('app_name : [%s]' % app_name);
print('app_location : [%s]' % app_location);
print('number_of_ms : [%s]' % number_of_ms);
print('ms_name_prefix : [%s]' % ms_name_prefix);

# Open default domain template
# ======================
readDomain(domain_path)

# Configure App
# =============
cd('/')
create(app_name, 'AppDeployment')
cd('/AppDeployments/%s/' % app_name)
set('StagingMode', 'nostage')
set('SourcePath', app_location)
targets = ms_name_prefix + str(1)
for index in range(2, number_of_ms + 1):
targets = targets + ',%s' % (ms_name_prefix + str(index))
set('Target', targets)

# Write Domain
# ============
updateDomain()

# Exit WLST
# =========
exit()
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
#! /usr/bin/bash
Copy link
Member

Choose a reason for hiding this comment

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

This launcher.sh script has no handlers for stop/start. You need to add handlers so that users can use docker stop effectively.

Copy link
Member Author

Choose a reason for hiding this comment

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

Hi Avi,

By handlers for stop, did you mean something like trapping (using trap) SIGKILL and SIGTERM and passing them on to server process?

What do you mean by a handler for start? Isn't launcher the script that will run when we start the container?

Copy link
Member

Choose a reason for hiding this comment

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

Yes, sorry. I meant handlers for SIGKILL and SIGTERM (which are what docker stop calls).

Copy link
Member Author

Choose a reason for hiding this comment

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

Hi Avi,

launcher.sh invokes startManagedWebLogic.sh. This script (startManagedWebLogic.sh) like startWebLogic.sh used by other docker samples is created during WebLogic domain creation. I think these scripts communicate these signals to the underlying JVM (or not at the very least not inhibit the transmission of signal to the underlying JVM). WLS running in JVM handles SIGTERM and SIGKILL correctly.

Copy link
Member

Choose a reason for hiding this comment

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

Have you tested and confirmed that the signal handlers still work as expected?

Copy link
Member Author

Choose a reason for hiding this comment

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

Hi Avi,

Following up on your question about behavior of docker stop with WLS, I experimented and found the following.

About docker stop

  1. docker stop sends a SIGTERM to the main process initially and then sends a SIGKILL after some time. This is a configurable value, defaults to 10 seconds.
  2. WebLogic java process handles SIGTERM to perform a forceShutdown() of the server, cleaning up a few things.
  3. When we launch WebLogic using generated shell scripts, sending SIGTERM to the pid of shell script doesn’t invoke the hook mentioned in Add Coherence Dockerfiles and scripts #2
  4. However if we find the pid of the java process (JVM that is running the server) and send a SIGTERM to it, shutdown hook mentioned in Add Coherence Dockerfiles and scripts #2 is invoked
  5. Trying to replicate Project description #3 in Docker image is equally ineffective. More specifically we can try and capture the pid of the process for the WLS startup script being launched as a part of docker container, but trapping SIGTERM (on docker stop) and forwarding to that captured pid is ineffective (like Project description #3)
  6. Perhaps we can replicate Reestruction of folders and scripts #4 in docker image i.e. try to trap SIGTERM and translate to a SIGTERM to all running java processes. But I am having trouble with this because we use oracle slim image in PS2 docker image and “ps” is not available.
  7. For WLS MSI docker image, I have been using the generated WLS script called startManagedWebLogic.sh. But I believe that observations in Project description #3 and Revised work  #5 will be the same if we use startWebLogic.sh for admin server in a regular WLS docker image

About docker kill

docker kill results in a SIGKILL signal. There is no way to intercept or trap it. That is also the case when we send a SIGKILL signal to a WLS server started with shell scripts (outside docker)

Copy link
Member

Choose a reason for hiding this comment

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

Is this behaviour replicated in the base WebLogic image or introduced by your addition of the launcher.sh script? If the former, please open another issue so that @mriccell can look into that. If the latter, you'll need to reimplement the handlers so that the SIGTERM is sent to the right pid.

Copy link
Member Author

Choose a reason for hiding this comment

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

Hi Avi,

As suspected, docker stop isn't converted to a forceShutdown request for WLS server. Here is what I tried:
docker pull container-registry.oracle.com/middleware/weblogic:12.2.1.1
docker run container-registry.oracle.com/middleware/weblogic:12.2.1.1

And then on the side I issued a docker stop request using a generated container name

docker stop epic_meitner

I can see that shutdown hook is not invoked, and the container stopped after 10 seconds (the default difference between the time SIGTERM and SIGKILL are sent to the container process)

Had it worked, I would have expected to see something like the following on stdout of the container:

<Jun 5, 2017 3:18:30,533 PM PDT>
<Jun 5, 2017 3:18:30,534 PM PDT> <Server shutdown has been requested by .>
<Jun 5, 2017 3:18:30,538 PM PDT>
<Jun 5, 2017 3:18:30,549 PM PDT>
<Jun 5, 2017 3:18:30,549 PM PDT>
<Jun 5, 2017 3:18:30,561 PM PDT>
<Jun 5, 2017 3:18:30,601 PM PDT> <JMX Connector Server stopped at service:jmx:iiop://10.147.117.136:7001/jndi/weblogic.management.mbeanservers.edit.>
<Jun 5, 2017 3:18:30,602 PM PDT> <JMX Connector Server stopped at service:jmx:iiop://10.147.117.136:7001/jndi/weblogic.management.mbeanservers.domainruntime.>
<Jun 5, 2017 3:18:30,666 PM PDT> <JMX Connector Server stopped at service:jmx:iiop://10.147.117.136:7001/jndi/weblogic.management.mbeanservers.runtime.>
Stopping Derby server...
Derby server stopped.

Copy link
Member

@Djelibeybi Djelibeybi Jun 6, 2017

Choose a reason for hiding this comment

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

Can you please open a new issue for this, so that @mriccell can take a look?

Copy link
Member

Choose a reason for hiding this comment

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

This should be #!/bin/bash


ms_name_from_image=${DEFAULT_MS_NAME}
number_of_ms=${NUMBER_OF_MS}
ms_name=${MS_NAME:-${MS_NAME_PREFIX}$(( ( RANDOM % $number_of_ms ) + 1 ))}
domain_home=${DOMAINS_DIR}/${DOMAIN_NAME}

echo "Launching with parameters"
echo "Domain Home: " $domain_home
echo "MS Name from Image: " $ms_name_from_image
echo "MS Name to be used: " $ms_name
echo "Number of servers configured in image: " $number_of_ms

cd $domain_home

# Rename the server directory
if [ "$ms_name_from_image" != "$ms_name" ]; then
echo "Setting up server name as $ms_name"
mv servers/$ms_name_from_image servers/$ms_name
fi

bin/startManagedWebLogic.sh $ms_name

Copy link
Member

Choose a reason for hiding this comment

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

If the rest of this script is not needed (it's all commented out) then just remove those lines.

# Relays SIGTERM to all java processes
# function relay_SIGTERM {
# pid=`grep java /proc/[0-9]*/comm | awk -F / '{ print $3; }'`
# echo "Sending SIGTERM to java process " $pid
# kill -SIGTERM $pid
#}

#trap relay_SIGTERM SIGTERM

# bin/startManagedWebLogic.sh $ms_name &
# while true
# do
# tail -f /dev/null & wait ${!}
# done
Loading