Skip to content

Commit bfbee7e

Browse files
committed
Multi-stage Dockerfile sample
1 parent ea10f5f commit bfbee7e

File tree

5 files changed

+85
-22
lines changed

5 files changed

+85
-22
lines changed

samples/README.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,11 @@ For example
6464
go run amqsput.go DEV.QUEUE.1 QM1
6565
```
6666

67+
The amqsput.go program also allows the queue and queue manager names to
68+
be provided by environment variables, to show another configuration
69+
mechanism. That approach will often be used in container deployments,
70+
and is demonstrated in the runSample set of files.
71+
6772
### Publish/Subscribe testing
6873
You will probably want to run `amqssub` JUST BEFORE running `amqspub` to ensure
6974
there is something waiting to receive the publications when they are made. The
@@ -74,6 +79,10 @@ There is an set of files in here that will show how to create a container that r
7479
the `amqsput` program. The `runSample.sh` script drives the process. It will try to
7580
connect to a queue manager running on the host machine.
7681

82+
The process is split into two pieces - the first is used to compile the program, and
83+
the second creates a (hopefully) smaller container with just the components needed
84+
to run the program.
85+
7786
## More information
7887
Comments in the programs explain what they are doing. For more detailed information about the
7988
MQ API, the functions, structures, and constants, see the

samples/amqsbo.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ import (
4040
"fmt"
4141
"os"
4242
"strings"
43-
"time"
43+
"time"
4444

4545
"github.com/ibm-messaging/mq-golang/v5/ibmmq"
4646
)
@@ -210,7 +210,7 @@ func mainWithRc() int {
210210
qMgrObject.Cmit()
211211
} else {
212212
// In real life, there would be some processing of the message here before deciding to backout or
213-
// commit the transaction. But here we will always to the backout.
213+
// commit the transaction. But here we will always do the backout.
214214
qMgrObject.Back()
215215

216216
// Adding an increasing delay in here may help with some error conditions so you don't just spin quickly.

samples/amqsput.go

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@
44
*
55
* The queue and queue manager name can be given as parameters on the
66
* command line. Defaults are coded in the program.
7+
* This sample also permits use of environment variables for the
8+
* parameters, which might be preferable in some container
9+
* deployments.
710
*
811
* A single message is put, containing a "hello" and timestamp.
912
* Each MQI call prints its success or failure. The MsgId of the
@@ -14,7 +17,7 @@
1417
package main
1518

1619
/*
17-
Copyright (c) IBM Corporation 2018
20+
Copyright (c) IBM Corporation 2018,2021
1821
1922
Licensed under the Apache License, Version 2.0 (the "License");
2023
you may not use this file except in compliance with the License.
@@ -54,8 +57,16 @@ func main() {
5457
func mainWithRc() int {
5558

5659
// The default queue manager and queue to be used. These can be overridden on command line.
57-
qMgrName := "QM1"
58-
qName := "DEV.QUEUE.1"
60+
// Environment variables can also be used as that works well in a number of common
61+
// container deployment models.
62+
qMgrName := os.Getenv("QMGR")
63+
if qMgrName == "" {
64+
qMgrName = "QM1"
65+
}
66+
qName := os.Getenv("QUEUE")
67+
if qName == "" {
68+
qName = "DEV.QUEUE.1"
69+
}
5970

6071
fmt.Println("Sample AMQSPUT.GO start")
6172

samples/runSample.Dockerfile

Lines changed: 56 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# © Copyright IBM Corporation 2019, 2020
1+
# © Copyright IBM Corporation 2019, 2021
22
#
33
# Licensed under the Apache License, Version 2.0 (the "License");
44
# you may not use this file except in compliance with the License.
@@ -12,12 +12,29 @@
1212
# See the License for the specific language governing permissions and
1313
# limitations under the License.
1414

15-
ARG BASE_IMAGE=ubuntu:18.04
16-
FROM $BASE_IMAGE
1715

16+
# This Dockerfile has two separate stages.
17+
#
18+
# The first stage is used to compile the Go program, where we need tools like the Go and C compilers.
19+
# The second stage is a runtime-only container that holds just the things we need to
20+
# execute the compiled program.
21+
#
22+
# Files and directories are copied from the builder container to the runtime container as needed.
23+
# Just for fun, I've used two different base images, trying to get the runtime image as small
24+
# as possible while still using a "regular" libc-based container.
25+
26+
# Start by setting some global variables that can still be overridden on the build command line.
27+
ARG BASE_IMAGE=ubuntu:18.04
1828
ARG GOPATH_ARG="/go"
1929
ARG GOVERSION=1.13.15
2030

31+
###########################################################
32+
# This starts the BUILD phase
33+
###########################################################
34+
FROM $BASE_IMAGE AS builder
35+
36+
ARG GOVERSION
37+
ARG GOPATH_ARG
2138
ENV GOVERSION=${GOVERSION} \
2239
GOPATH=$GOPATH_ARG \
2340
GOTAR=go${GOVERSION}.linux-amd64.tar.gz \
@@ -43,7 +60,7 @@ RUN export DEBIAN_FRONTEND=noninteractive \
4360
build-essential \
4461
&& rm -rf /var/lib/apt/lists/*
4562

46-
# Create location for the go programs and the MQ installation
63+
# Create a location for the go programs and the MQ installation
4764
RUN mkdir -p $GOPATH/src $GOPATH/bin $GOPATH/pkg \
4865
&& chmod -R 777 $GOPATH \
4966
&& cd /tmp \
@@ -57,7 +74,7 @@ RUN mkdir -p $GOPATH/src $GOPATH/bin $GOPATH/pkg \
5774
# Location of the downloadable MQ client package \
5875
ENV RDURL="https://public.dhe.ibm.com/ibmdl/export/pub/software/websphere/messaging/mqdev/redist" \
5976
RDTAR="IBM-MQC-Redist-LinuxX64.tar.gz" \
60-
VRMF=9.2.2.0
77+
VRMF=9.2.3.0
6178

6279
# Install the MQ client from the Redistributable package. This also contains the
6380
# header files we need to compile against. Setup the subset of the package
@@ -67,23 +84,48 @@ ENV genmqpkg_incnls=1 \
6784
genmqpkg_inctls=1
6885

6986
RUN cd /opt/mqm \
70-
&& curl -LO "$RDURL/$VRMF-$RDTAR" \
71-
&& tar -zxf ./*.tar.gz \
72-
&& rm -f ./*.tar.gz \
73-
&& bin/genmqpkg.sh -b /opt/mqm
87+
&& curl -LO "$RDURL/$VRMF-$RDTAR" \
88+
&& tar -zxf ./*.tar.gz \
89+
&& rm -f ./*.tar.gz \
90+
&& bin/genmqpkg.sh -b /opt/mqm
7491

7592
# We need the Go compiler in our PATH
7693
ENV PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/lib/go-$GOVERSION/bin
7794

7895
# Copy the source file over. We also need a go.mod file
7996
# The source for that has a different name in the repo so it doesn't accidentally get
80-
# used and we rename it during this copy.
81-
COPY amqsput.go $GOPATH_ARG/src
97+
# used. We rename it during this copy.
98+
COPY amqsput.go $GOPATH_ARG/src
8299
COPY runSample.gomod $GOPATH_ARG/src/go.mod
83100

84101
# Do the actual compile. This will automatically download the ibmmq package
85102
RUN cd $GOPATH_ARG/src && go build -o $GOPATH_ARG/bin/amqsput amqsput.go
86103

87-
# The startup script will set MQSERVER and optionally set
88-
# more environment variables that will be passed to amqsput through this entrypoint.
89-
ENTRYPOINT /go/bin/amqsput $QUEUE $QMGR
104+
###########################################################
105+
# This starts the RUNTIME phase
106+
###########################################################
107+
# Now that there is a container with the compiled program we can build a smaller
108+
# runtime image. Start from one of the smaller base container images.
109+
FROM debian:stretch-slim
110+
ARG GOPATH_ARG
111+
ARG GOVERSION
112+
113+
# Copy over the MQ runtime client code. This does preserve the .h files used during compile
114+
# but those are tiny so there's no real space-saving from deleting them here.
115+
COPY --from=builder /opt/mqm /opt/mqm
116+
117+
# Create some directories that may be needed at runtime, depending on the container's
118+
# security environment.
119+
RUN mkdir -p /IBM/MQ/data/errors \
120+
&& mkdir -p /.mqm \
121+
&& chmod -R 777 /IBM \
122+
&& chmod -R 777 /.mqm \
123+
&& mkdir -p /go/bin
124+
125+
# The actual program has all of the Go runtime embedded; we only need the single
126+
# binary along with the MQ client libraries, for it to run.
127+
COPY --from=builder $GOPATH_ARG/bin/amqsput /go/bin/amqsput
128+
129+
# The startup script will set MQSERVER and optionally set more
130+
# environment variables that will be passed to amqsput through this entrypoint.
131+
ENTRYPOINT [ "/go/bin/amqsput" ]

samples/runSample.sh

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@ function latestSemVer {
1010
# Assume repo tags have been created in a sensible order. Find the mq-golang
1111
# version in the root go.mod file and the current Git tag for this repo.
1212
# Then pick the latest version to create the Docker tag
13-
VERDEP=`cat ../go.mod | awk '/mq-golang/ {print $2}' `
14-
VERREPO=`git tag -l | sort | tail -1 `
13+
VERDEP=`cat ../../go.mod | awk '/mq-golang/ {print $2}' `
14+
VERREPO=`git tag -l 2>/dev/null| sort | tail -1 `
1515

1616
VER=`latestSemVer $VERDEP $VERREPO`
1717
if [ -z "$VER" ]
@@ -25,6 +25,7 @@ echo Building container with tag $TAG:$VER
2525

2626
# Build the container which includes compilation of the program
2727
docker build -t $TAG:$VER -f runSample.Dockerfile .
28+
2829
if [ $? -eq 0 ]
2930
then
3031
# This line grabs a currently active IPv4 address for this machine. It's probably
@@ -36,7 +37,7 @@ then
3637

3738
if [ ! -z "addr" ]
3839
then
39-
# Run the container. Can override default command line values in amqsput voa
40+
# Run the container. Can override default command line values in amqsput via
4041
# env vars here.
4142
docker run -e MQSERVER="SYSTEM.DEF.SVRCONN/TCP/$addr($port)" \
4243
-e QUEUE=DEV.QUEUE.1 \

0 commit comments

Comments
 (0)