|
| 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. |
0 commit comments