Skip to content

Commit 7e3081d

Browse files
authored
Merge pull request #2111 from oracle-devrel/ci-nginx-with-volumes-example
ci-nginx-with-volumes-example
2 parents be3a231 + 3bc1cb9 commit 7e3081d

File tree

10 files changed

+1223
-0
lines changed

10 files changed

+1223
-0
lines changed
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
Copyright (c) 2025 Oracle and/or its affiliates.
2+
3+
The Universal Permissive License (UPL), Version 1.0
4+
5+
Subject to the condition set forth below, permission is hereby granted to any
6+
person obtaining a copy of this software, associated documentation and/or data
7+
(collectively the "Software"), free of charge and under any and all copyright
8+
rights in the Software, and any and all patent rights owned or freely
9+
licensable by each licensor hereunder covering either (i) the unmodified
10+
Software as contributed to or provided by such licensor, or (ii) the Larger
11+
Works (as defined below), to deal in both
12+
13+
(a) the Software, and
14+
(b) any piece of software and/or hardware listed in the lrgrwrks.txt file if
15+
one is included with the Software (each a "Larger Work" to which the Software
16+
is contributed by such licensors),
17+
18+
without restriction, including without limitation the rights to copy, create
19+
derivative works of, display, perform, and distribute the Software and make,
20+
use, sell, offer for sale, import, export, have made, and have sold the
21+
Software and the Larger Work(s), and to sublicense the foregoing rights on
22+
either these or other terms.
23+
24+
This license is subject to the following condition:
25+
The above copyright notice and either this complete permission notice or at
26+
a minimum a reference to the UPL must be included in all copies or
27+
substantial portions of the Software.
28+
29+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
30+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
31+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
32+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
33+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
34+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
35+
SOFTWARE.
Lines changed: 241 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,241 @@
1+
<!--
2+
Copyright (c) 2025 Oracle and/or its affiliates.
3+
4+
The Universal Permissive License (UPL), Version 1.0
5+
6+
Subject to the condition set forth below, permission is hereby granted to any
7+
person obtaining a copy of this software, associated documentation and/or data
8+
(collectively the "Software"), free of charge and under any and all copyright
9+
rights in the Software, and any and all patent rights owned or freely
10+
licensable by each licensor hereunder covering either (i) the unmodified
11+
Software as contributed to or provided by such licensor, or (ii) the Larger
12+
Works (as defined below), to deal in both
13+
14+
(a) the Software, and
15+
(b) any piece of software and/or hardware listed in the lrgrwrks.txt file if
16+
one is included with the Software (each a "Larger Work" to which the Software
17+
is contributed by such licensors),
18+
19+
without restriction, including without limitation the rights to copy, create
20+
derivative works of, display, perform, and distribute the Software and make,
21+
use, sell, offer for sale, import, export, have made, and have sold the
22+
Software and the Larger Work(s), and to sublicense the foregoing rights on
23+
either these or other terms.
24+
25+
This license is subject to the following condition:
26+
The above copyright notice and either this complete permission notice or at
27+
a minimum a reference to the UPL must be included in all copies or
28+
substantial portions of the Software.
29+
30+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
31+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
32+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
33+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
34+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
35+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
36+
SOFTWARE.
37+
-->
38+
39+
# OCI Container Instances NGINX example
40+
## With multiple volumes and a custom sidecar to tail access log to OCI Logging and mount the filesystem from OCI Object Storage bucket
41+
42+
Reviewed: 9.10.2025
43+
44+
## When to use this asset?
45+
46+
Anyone who wants to experiment with OCI Container Instances and setup a multi-container instance with multiple volumes. In this example I'm using volumes to:
47+
<ul>
48+
<li>Mount the NGINX filesystem for html data from OCI Object Storage bucket</li>
49+
<li>Tail NGINX access log to OCI Logging for monitoring</li>
50+
</ul>
51+
These operations will be handled by a custom container that is being built in this example.<br>
52+
The NGINX container is the latest one from Docker Hub without modifications.<br>
53+
The sidecar container is built using <code>OCI SDK</code> in NodeJS, but this could be done also in an other language like Java, Go, Python or .net.
54+
55+
## Author
56+
<a href="https://github.com/mikarinneoracle">mikarinneoracle</a>
57+
58+
## How to use this asset?
59+
60+
First, the sidecar container is built from the <code>source</code> in this repo. This can be done in OCI tenancy Cloud Shell.<br>
61+
Once built it is pushed to OCI Registry (OCIR) repo for deployment as part of the to Container Instances (CI) deployment.
62+
<p>
63+
Then, the CI deployment is created in OCI Resource Manager (RM) from the <code>terraform</code> in this repo.
64+
<p>
65+
However, before creating the RM terraform stack a few other OCI resources need to be created for the CI deployment:
66+
<ul>
67+
<li>Object Storage (OS) bucket for the NGINX filesystem. The example content is under <code>www-data</code> in this repo. The NGINX container custom sidecar will mount these files to NGINX <code>/usr/share/nginx/html</code> volume directory</li>
68+
<li>OCI Logging target for the container sidecar to send the <code>access.log</code> with <code>tail</code> to</li>
69+
</ul>
70+
Once these are created, the RM stack can be created with a configuration that incudes these above among other variables and be deployed.<br>
71+
The result will be a working NGINX with html content from OS and access logs being to OCI Logging for monitoring.
72+
73+
## Steps to complete
74+
75+
### Create OCIR repo
76+
77+
In your OCI tenancy open Cloud UI.
78+
<p>
79+
Create a new repo <code>nginx-sidecar</code> to your home compartment. Keep it as private repo (the default setting).
80+
81+
### Create the sidecar container from source in Cloud Shell
82+
83+
#### Copy source from this repo
84+
85+
In your OCI tenancy open Cloud shell.
86+
<p>
87+
In cloud shell create subdir for the sidecar container with <code>mkdir nginx-sidecar</code> and cd to it.
88+
<br>
89+
Create the 3 files in <code>source</code> directory. There are several ways to do this but probably easiest is to just a <code>nano</code> editor and copy-paste file contents and save.
90+
<br>
91+
Other ways are to use the file upload from the cloud shell menu after cloning this repo to your localhost and using the Code Editor in the Cloud UI. Choose the one which suits you the best.
92+
<br>
93+
94+
#### Setup OCI SDK Authentication
95+
96+
Since the sidecar container uses OCI SDk to use other OCI services in tenancy we need authenticate and authorize it for the use.
97+
<p>
98+
Normally with any SDK code that runs inside OCI we use use either <code>instance-principal</code> or <code>resource-principal</code> for this purpose depending on the case. Anything that runs on a Virtual Machine (VM) uses <code>instance-principal</code> and services like OCI Functions and Container Instances like in this case use <code>resource-principal</code>. See <a href="https://docs.oracle.com/en-us/iaas/Content/API/Concepts/sdk_authentication_methods.htm">https://docs.oracle.com/en-us/iaas/Content/API/Concepts/sdk_authentication_methods.htm</a> for more info.
99+
<p>
100+
To make testing this example slightly easier let's use your IAM user instead. To do this we package your OCI CLI config into the container image. But be aware not to distribute the container outside your OCI tenancy since it contains your tenancy <code>API KEY</code>.
101+
<p>
102+
To do this create OCI config with OCI CLI in your localhost with <code>oci setup config</code> and copy the created config to your directory in cloud shell. After adding the created API KEY to your profile in OCI tenancy copy the created private key file to your directory in cloud shell, too. Modify the config with nano editor to remove the path from the keyfile e.g.
103+
<pre>key_file = oci_api_key.pem</pre>
104+
<p>
105+
Alternatively you can use <code>resource-principal</code> and to do this comment line 22 in <code>index.js</code> under <code>source</code> and respectively uncomment line 23.<br>
106+
To make resource-principal to work create also a dynamic group based on your compartment and apply necessary policies to make the SDK to be able to access both Object Storage and Logs.
107+
See <a href="https://docs.oracle.com/en-us/iaas/Content/Identity/dynamicgroups/To_create_a_dynamic_group.htm">https://docs.oracle.com/en-us/iaas/Content/Identity/dynamicgroups/To_create_a_dynamic_group.htm</a> for more info.
108+
109+
#### Build and push to OCIR
110+
111+
After adding the CLI config and API Key build the container and push it to OCIR repo:
112+
113+
<pre>
114+
export ns=$(oci os ns get | jq .data | tr -d '"')
115+
docker build . -t "fra.ocir.io/$ns/nginx-sidecar:1"
116+
docker push "fra.ocir.io/$ns/nginx-sidecar:1"
117+
</pre>
118+
119+
As always you can change the <code>region</code> to match yours, I'm using the <i>EU-frankurt-1</i> region in this case.
120+
121+
### Create Object Storage bucket with html in www-data
122+
123+
In Cloud UI create the Object Storage bucket to your compartment with name <code>nginx-www-data</code>.
124+
<p>
125+
You can manually upload the files in <code>www-data</code> of this repo after cloning using Cloud UI or use OCI CLI bulk upload in localhost to do this:
126+
<pre>
127+
cd www-data
128+
oci os object bulk-upload --bucket-name nginx-www-data --overwrite --src-dir .
129+
</pre>
130+
There is one consideration though:<br>
131+
CLI bulk upload uploads directories but it does not seem to set the "directory" type for directories unlike the Cloud UI by default, and since the container sidecar code expects this type to be able to copy the directory structure from OS I suggest first creating the directories to the bucket before using the CLI bulk upload.<br>
132+
Hence, in this example create also the <code>images</code> directory manually using Cloud UI to the bucket after creating it, before using the bulk upload to copy the files to the bucket.
133+
134+
### Create OCI Logging target for NGINX access log
135+
136+
In Cloud UI navigate to OCI Logging and create a Log with name <code>nginx-log</code> using the Default Log Group (if you don't have that one then create a Log Group first and then the Log itself).
137+
<p>
138+
The log's OCID need to be then configured to the Resorce Manager Terraform stack variables in the later step.
139+
140+
### Create a VCN with a public subnet for NGINX access to port 80 from Internet
141+
142+
In Cloud create a new Virtual Cloud Network with a subnet having public Internet access.
143+
The adjust the public subnet's security list ingress rule to allow traffic from CIDR <code>0.0.0.0/</code> to port 80.
144+
<p>
145+
The subnet's OCID need to be then configured to the Resorce Manager Terraform stack variables in next step.
146+
147+
### Create Resource Manager stack from terraform files
148+
149+
In Cloud UI create a RM new stack in your home compartment.
150+
<p>
151+
First copying the <code>terraform</code> directory to your localhost either by cloning this repo or copy-pasting the 2 files manually into a local directory named <code>terraform</code>.
152+
<p>
153+
Then drag-and-drop the directory folder to the Stack Configuration box on the Cloud UI's Create Stack screen. Now, click "Next" to setup the variables for the stack:
154+
<p>
155+
<ul>
156+
<li><b>ad_number</b> : 1 (or 2 or 3 if your region supports it)</li>
157+
<li><b>compartment_ocid</b> : current compartment OCID</li>
158+
<li><b>log_file</b> : access.log</li>
159+
<li><b>log_mount_name</b> : nginxlogs</li>
160+
<li><b>log_mount_path</b> : /var/log/nginx</li>
161+
<li><b>log_ocid</b> : Here copy the OCID of the Log created in earlier step</li>
162+
<li><b>sidecar_image</b> : Here copy the sidecar image url e.g. fra.ocir.io/namespace/nginx-sidecar:1</li>
163+
<li><b>subnet_ocid</b> : Here copy the OCID of the public subnet created in previous step</li>
164+
<li><b>tenancy_ocid</b> : current tenancy OCID</li>
165+
<li><b>www_data_bucket</b> : nginx-www-data</li>
166+
<li><b>www_mount_name</b> : nginxdata</li>
167+
<li><b>www_mount_path</b> : /usr/share/nginx/html</li>
168+
</ul>
169+
170+
So, there are only 3 variables to be filled in by you (other are defaults):
171+
<code>log_ocid</code>, <code>subnet_ocid</code> and the <code>sidecar_image</code>.
172+
173+
<p>
174+
Also, as it can be seen we are using NGINX defaults for access.log and html data directory to create CI <code>volumes</code> and <code>volume_mounts</code> for the containers in the deployment (i.e. NGINX and the custom sidecar container).
175+
176+
### Run the the RM stack to create the CI deployment and test NGINX
177+
178+
This is the final step to apply the RM stack in the Cloud UI, simply navigate to the stack details and click "Apply" which will run the stack.
179+
<p>
180+
The result is a CI instance named <code>Nginx with OCI SDK sidecar</code> and navigate to it in the Cloud UI.
181+
<p>
182+
Navigate to containers and 2 containers should be running as part of the CI instance deployment:
183+
<p>
184+
<ul>
185+
<li>nginx</li>
186+
<li>nginx-sidecar</li>
187+
</ul>
188+
Navigate to <code>nginx-sidecar</code>, click the "View environment variables" -button and you should these key-values on the screen:
189+
<p>
190+
<ul>
191+
<li>log_file : /var/log/nginx/access.log</li>
192+
<li>log_ocid : <i>OCID of the Log that was created in earlier step</i></li>
193+
<li>os_bucket : nginx-www-data</li>
194+
<li>www_path : /usr/share/nginx/html</li>
195+
</ul>
196+
<p>
197+
Now, close this, click the "View logs" -button and this log should appear on the screen (example):
198+
<pre>
199+
2025-10-09T11:45:19.882545929Z stdout F OCI LOG:ocid1.log.oc1.eu-frankfurt-1.amaaaaaauev...ae5q
200+
2025-10-09T11:45:19.88275791Z stdout F ACCESS LOG:/var/log/nginx/access.log
201+
2025-10-09T11:45:19.88276303Z stdout F WWW DATA:/usr/share/nginx/html
202+
2025-10-09T11:45:19.882795Z stdout F OS BUCKET:nginx-www-data
203+
2025-10-09T11:45:20.046498505Z stdout F images/
204+
2025-10-09T11:45:20.085388327Z stdout F images/ is a directory, creating ..
205+
2025-10-09T11:45:20.08573349Z stdout F images/nginx_logo.svg
206+
2025-10-09T11:45:20.117605278Z stdout F /usr/share/nginx/html/images/nginx_logo.svg
207+
2025-10-09T11:45:20.117760561Z stdout F index.html
208+
2025-10-09T11:45:20.121175176Z stdout F File written successfully to/usr/share/nginx/html/images/nginx_logo.svg
209+
2025-10-09T11:45:20.141964765Z stdout F /usr/share/nginx/html/index.html
210+
2025-10-09T11:45:20.142309646Z stdout F File written successfully to/usr/share/nginx/html/index.html
211+
</pre>
212+
213+
Close this, copy the <code>Public IP address</code> and paste it to your browser. Now, the NGINX website should show up with the html content mounted from OS bucket:
214+
<p>
215+
<img src="files/nginx.jpg" width=800 />
216+
<p>
217+
218+
Now go back to Cloud UI to check the OCI Logging. Under Logs find the log <code>nginx-log</code> and see log rows from the NGINX access.log starting to appear on the screen.
219+
220+
## Useful Links
221+
222+
- [OCI Container Instances](https://www.oracle.com/cloud/cloud-native/container-instances/)
223+
- Learn how OCI Container Instances lets you easily run applications on serverless compute optimized for containers
224+
- [OCI SDK](https://docs.oracle.com/en-us/iaas/Content/API/Concepts/sdks.htm)
225+
- Oracle Cloud Infrastructure provides a number of Software Development Kits (SDKs) and a Command Line Interface (CLI) to facilitate development of custom solutions
226+
- [OCI Logging](https://docs.oracle.com/en-us/iaas/Content/Logging/Concepts/loggingoverview.htm)
227+
- The Oracle Cloud Infrastructure Logging service is a highly scalable and fully managed single pane of glass for all the logs in your tenancy. Logging provides access to logs from Oracle Cloud Infrastructure resources
228+
- [OCI Object Storage](https://www.oracle.com/cloud/storage/object-storage/)
229+
- Oracle Cloud Infrastructure (OCI) Object Storage provides scalable, durable, low-cost storage for any type of data. Benefit from 11 nines of durability. Scale storage to nearly unlimited capacity for your unstructured data
230+
- [Oracle](https://www.oracle.com/)
231+
- Oracle Website
232+
233+
## License
234+
235+
Copyright (c) 2025 Oracle and/or its affiliates.
236+
237+
Licensed under the Universal Permissive License (UPL), Version 1.0.
238+
239+
See [LICENSE](LICENSE) for more details.
240+
241+
ORACLE AND ITS AFFILIATES DO NOT PROVIDE ANY WARRANTY WHATSOEVER, EXPRESS OR IMPLIED, FOR ANY SOFTWARE, MATERIAL OR CONTENT OF ANY KIND CONTAINED OR PRODUCED WITHIN THIS REPOSITORY, AND IN PARTICULAR SPECIFICALLY DISCLAIM ANY AND ALL IMPLIED WARRANTIES OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. FURTHERMORE, ORACLE AND ITS AFFILIATES DO NOT REPRESENT THAT ANY CUSTOMARY SECURITY REVIEW HAS BEEN PERFORMED WITH RESPECT TO ANY SOFTWARE, MATERIAL OR CONTENT CONTAINED OR PRODUCED WITHIN THIS REPOSITORY. IN ADDITION, AND WITHOUT LIMITING THE FOREGOING, THIRD PARTIES MAY HAVE POSTED SOFTWARE, MATERIAL OR CONTENT TO THIS REPOSITORY WITHOUT ANY REVIEW. USE AT YOUR OWN RISK.
64.3 KB
Loading
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
FROM node:22.20-alpine
2+
3+
WORKDIR /
4+
COPY ./ /
5+
6+
RUN npm install
7+
8+
CMD [ "node", "index.js" ]

0 commit comments

Comments
 (0)