DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Please enter at least three characters to search
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Zones

Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

The software you build is only as secure as the code that powers it. Learn how malicious code creeps into your software supply chain.

Apache Cassandra combines the benefits of major NoSQL databases to support data management needs not covered by traditional RDBMS vendors.

Generative AI has transformed nearly every industry. How can you leverage GenAI to improve your productivity and efficiency?

Modernize your data layer. Learn how to design cloud-native database architectures to meet the evolving demands of AI and GenAI workloads.

Related

  • Building REST API Backend Easily With Ballerina Language
  • End-to-End REST Service Testing on Oracle Database
  • Jakarta Security and REST in the Cloud: Part 2 Getting to Know the Basics
  • Jakarta Security and REST in the Cloud Part 1: Hello World

Trending

  • Contextual AI Integration for Agile Product Teams
  • Building Custom Tools With Model Context Protocol
  • Cloud Cost Optimization for ML Workloads With NVIDIA DCGM
  • Navigating the LLM Landscape: A Comparative Analysis of Leading Large Language Models
  1. DZone
  2. Data Engineering
  3. Databases
  4. Creating an Oracle REST Data Services Docker Image

Creating an Oracle REST Data Services Docker Image

Take a look at this article to learn how to create a Docker image for your ORDS instance now that Oracle has added it to the Docker build family files.

By 
Gerald Venzl user avatar
Gerald Venzl
·
May. 25, 18 · Tutorial
Likes (1)
Comment
Save
Tweet
Share
9.5K Views

Join the DZone community and get the full member experience.

Join For Free

Oracle has added Oracle REST Data Services (ORDS) to the Docker build files family on GitHub, which means that you can now easily dockerize ORDS. If you don't know yet what ORDS is, it's a free technology from Oracle that allows you to REST-enable your Oracle databases. More specifically, with ORDS you can just fire off regular REST calls to modify or retrieve data from one or many Oracle databases without having to know how to write SQL (not that knowing SQL is a bad thing!). In modern application and microservices architectures REST has become more and more popular for exchanging information. ORDS enables you to easily exchange data from and to Oracle databases via REST without having to write lines and lines of code yourself. For more information on what ORDS is and what it can do, check out Jeff Smith's blog post about ORDS.

What You Need

  • The ORDS install zip file, you can download it from the Oracle Technology Network
  • An Java Server JRE 8 Docker base image
  • An Oracle Database running somewhere that ORDS should expose via REST

Environment

My environment as of writing this blog is as follows:

  • Oracle Linux 7.4 (4.1.12-112.14.15.el7uek.x86_64)
  • Docker 17.06.2-ol (docker-engine.x86_64 17.06.2.ol-1.0.1.el7)
  • Java Server JRE 1.8.0_172
  • Oracle Rest Data Services 18.1.1

Building the Oracle REST Data Services Docker Image

Obtaining the Required Files

As with all the GitHub build files from Oracle you first have to download them. There are various ways of how you can download them. For example, you can just clone the Git repository directly. Or you can just download a zip file from GitHub containing all the required files. This option is best for people who don't know Git. The URL to the zip file is https://github.com/oracle/docker-images/archive/master.zip, which you can download via wget or with your browser and then unzip:

$ wget https://github.com/oracle/docker-images/archive/master.zip
--2018-05-04 14:20:26-- https://github.com/oracle/docker-images/archive/master.zip
Resolving github.com (github.com)... 192.30.255.113, 192.30.255.112
Connecting to github.com (github.com)|192.30.255.113|:443... connected.
HTTP request sent, awaiting response... 302 Found
Location: https://codeload.github.com/oracle/docker-images/zip/master [following]
--2018-05-04 14:20:26-- https://codeload.github.com/oracle/docker-images/zip/master
Connecting to codeload.github.com (codeload.github.com)|192.30.255.120|:443... connected.
Proxy request sent, awaiting response... 200 OK
Length: unspecified [application/zip]
Saving to: 'master.zip'

[ <=> ] 7,601,317 5.37MB/s in 1.3s

2018-05-04 14:20:28 (5.37 MB/s) - 'master.zip' saved [7601317]

$ unzip master.zip
Archive: master.zip
184cded65f147766c41b2179ee31ba5551185507
creating: docker-images-master/
extracting: docker-images-master/.gitattributes
inflating: docker-images-master/.gitignore
extracting: docker-images-master/.gitmodules
inflating: docker-images-master/CODEOWNERS
inflating: docker-images-master/CONTRIBUTING.md
...
...
...
creating: docker-images-master/OracleRestDataServices/
extracting: docker-images-master/OracleRestDataServices/.gitignore
inflating: docker-images-master/OracleRestDataServices/COPYRIGHT
inflating: docker-images-master/OracleRestDataServices/LICENSE
inflating: docker-images-master/OracleRestDataServices/README.md
creating: docker-images-master/OracleRestDataServices/dockerfiles/
...
...
...
inflating: docker-images-master/README.md
$

Next you will have to download the ORDS Installer zip file. As said above, you can get it from the Oracle Technology Network:

$ ls -al ords.18*.zip
-rw-r--r--. 1 oracle oracle 61118609 May 4 14:38 ords.18.1.1.95.1251.zip

Building the Java Server JRE Base Image

The ORDS Docker image is built on the oracle/serverjre:8 base image. That image is not on the Docker Hub so Docker cannot just pull the image automatically. Instead, you first have to build that image before you can proceed to building the ORDS image. Building the Java Server JRE image is straight forward. First you need to download the latest server-jre-8*linux-x64.tar.gz file from the Oracle Technology Network:

$ ls -al server-jre*.tar.gz
-rw-r--r--. 1 oracle oracle 54817401 May 4 14:30 server-jre-8u172-linux-x64.tar.gz

Once you have the file, copy it into the OracleJava/java-8 folder and run the Java Server JRE Docker build.sh script:

$ cd docker-images-master/OracleJava/java-8
$ cp ~/server-jre-8u172-linux-x64.tar.gz .
$ ./build.sh
Sending build context to Docker daemon 54.82MB
Step 1/5 : FROM oraclelinux:7-slim
---> 9870bebfb1d5
Step 2/5 : MAINTAINER Bruno Borges <bruno.borges@oracle.com>
---> Running in b1847c1a647e
---> 3bc9baedf526
Removing intermediate container b1847c1a647e
Step 3/5 : ENV JAVA_PKG server-jre-8u*-linux-x64.tar.gz JAVA_HOME /usr/java/default
---> Running in 50998175529b
---> 017598682688
Removing intermediate container 50998175529b
Step 4/5 : ADD $JAVA_PKG /usr/java/
---> 6704a281de8b
Removing intermediate container b6b6a08d3c38
Step 5/5 : RUN export JAVA_DIR=$(ls -1 -d /usr/java/*) && ln -s $JAVA_DIR /usr/java/latest && ln -s $JAVA_DIR /usr/java/default && alternatives --install /usr/bin/java java $JAVA_DIR/bin/java 20000 && alternatives --install /usr/bin/javac javac $JAVA_DIR/bin/javac 20000 && alternatives --install /usr/bin/jar jar $JAVA_DIR/bin/jar 20000
---> Running in 281fe2343d2c
---> f65b2559f3a5
Removing intermediate container 281fe2343d2c
Successfully built f65b2559f3a5
Successfully tagged oracle/serverjre:8
$

That's it! Now you have a brand new oracle/serverjre:8 Docker image:

$ docker images
REPOSITORY          TAG            IMAGE ID        CREATED           SIZE
oracle/serverjre    8              f65b2559f3a5    45 seconds ago    269MB
oracle/database     12.2.0.1-se2   323887b92e8f    3 weeks ago       6.38GB
oracle/database     12.2.0.1-ee    08d230aa1d55    3 weeks ago       6.39GB
oracle/database     12.1.0.2-se2   b4999e09453e    3 weeks ago       5.08GB
oracle/database     12.1.0.2-ee    aee62bc26119    3 weeks ago       5.18GB
oracle/database     11.2.0.2-xe    50712d409891    3 weeks ago       809MB
oraclelinux         7-slim         9870bebfb1d5    5 months ago      118MB
$

Building the ORDS Docker Image

Once you have the oracle/serverjre:8 Docker image on your machine you can now go ahead and build the actual ORDS Docker image. This is also a rather easy task, just put the installer zip file into the OracleRestDataServices/dockerfiles/ folder and run the buildDockerImage.sh script:

$ cd ../../OracleRestDataServices/dockerfiles/
$ mv ~/ords.18.1.1.95.1251.zip .
$ ./buildDockerImage.sh
Checking if required packages are present and valid...
ords.18.1.1.95.1251.zip: OK
==========================
DOCKER info:
Containers: 2
Running: 0
Paused: 0
Stopped: 2
Images: 10
Server Version: 17.06.2-ol
Storage Driver: btrfs
Build Version: Btrfs v4.9.1
Library Version: 102
Logging Driver: json-file
Cgroup Driver: cgroupfs
Plugins:
Volume: local
Network: bridge host ipvlan macvlan null overlay
Log: awslogs fluentd gcplogs gelf journald json-file logentries splunk syslog
Swarm: inactive
Runtimes: runc
Default Runtime: runc
Init Binary: docker-init
containerd version: 6e23458c129b551d5c9871e5174f6b1b7f6d1170
runc version: 810190ceaa507aa2727d7ae6f4790c76ec150bd2
init version: 949e6fa
Security Options:
seccomp
Profile: default
selinux
Kernel Version: 4.1.12-112.14.15.el7uek.x86_64
Operating System: Oracle Linux Server 7.4
OSType: linux
Architecture: x86_64
CPUs: 2
Total Memory: 7.795GiB
Name: localhost.localdomain
ID: GZ5A:XQWB:F5TE:56JE:GR3J:VCXJ:I7BO:EGMY:K52K:JAS3:A7ZC:BOHQ
Docker Root Dir: /var/lib/docker
Debug Mode (client): false
Debug Mode (server): false
Registry: https://index.docker.io/v1/
Experimental: true
Insecure Registries:
127.0.0.0/8
Live Restore Enabled: false

==========================
Proxy settings were found and will be used during build.
Building image 'oracle/restdataservices:18.1.1' ...
Sending build context to Docker daemon 61.14MB
Step 1/10 : FROM oracle/serverjre:8
---> f65b2559f3a5
Step 2/10 : LABEL maintainer "gerald.venzl@oracle.com"
---> Running in d90ea0da50ae
---> 8959f49c8b7b
Removing intermediate container d90ea0da50ae
Step 3/10 : ENV ORDS_HOME /opt/oracle/ords INSTALL_FILE ords*.zip CONFIG_PROPS "ords_params.properties.tmpl" STANDALONE_PROPS "standalone.properties.tmpl" RUN_FILE "runOrds.sh"
---> Running in 84ae509c3b08
---> 595f8228d224
Removing intermediate container 84ae509c3b08
Step 4/10 : COPY $INSTALL_FILE $CONFIG_PROPS $STANDALONE_PROPS $RUN_FILE $ORDS_HOME/
---> 992d15c48302
Removing intermediate container 3088dd27464e
Step 5/10 : RUN mkdir -p $ORDS_HOME/doc_root && chmod ug+x $ORDS_HOME/*.sh && groupadd dba && useradd -d /home/oracle -g dba -m -s /bin/bash oracle && cd $ORDS_HOME && jar -xf $INSTALL_FILE && rm $INSTALL_FILE && mkdir -p $ORDS_HOME/config/ords && java -jar $ORDS_HOME/ords.war configdir $ORDS_HOME/config && chown -R oracle:dba $ORDS_HOME
---> Running in a84bc25b8eb3
May 04, 2018 6:42:22 PM
INFO: Set config.dir to /opt/oracle/ords/config in: /opt/oracle/ords/ords.war
---> 6ccfc92744ed
Removing intermediate container a84bc25b8eb3
Step 6/10 : USER oracle
---> Running in c41c77b49add
---> 2bd11f2f8008
Removing intermediate container c41c77b49add
Step 7/10 : WORKDIR /home/oracle
---> bc31d79cfb4a
Removing intermediate container efef9dccf774
Step 8/10 : VOLUME $ORDS_HOME/config/ords
---> Running in dfbc7ee6f967
---> 0ee4e7ed71b1
Removing intermediate container dfbc7ee6f967
Step 9/10 : EXPOSE 8888
---> Running in deaebbf2950b
---> 25d777caccca
Removing intermediate container deaebbf2950b
Step 10/10 : CMD $ORDS_HOME/$RUN_FILE
---> Running in 0c2270a7fac4
---> 4ee1ac73e1f9
Removing intermediate container 0c2270a7fac4
Successfully built 4ee1ac73e1f9
Successfully tagged oracle/restdataservices:18.1.1

Oracle Rest Data Services version 18.1.1 is ready to be extended:

--> oracle/restdataservices:18.1.1

Build completed in 19 seconds.

$

And now you have a brand new ORDS Docker image, in my case containing ORDS 18.1.1:

$ docker images
REPOSITORY                 TAG             IMAGE ID        CREATED           SIZE
oracle/restdataservices    18.1.1          4ee1ac73e1f9    52 seconds ago    395MB
oracle/serverjre           8               f65b2559f3a5    10 minutes ago    269MB
oracle/database            12.2.0.1-se2    323887b92e8f    3 weeks ago       6.38GB
oracle/database            12.2.0.1-ee     08d230aa1d55    3 weeks ago       6.39GB
oracle/database            12.1.0.2-se2    b4999e09453e    3 weeks ago       5.08GB
oracle/database            12.1.0.2-ee     aee62bc26119    3 weeks ago       5.18GB
oracle/database            11.2.0.2-xe     50712d409891    3 weeks ago       809MB
oraclelinux                7-slim          9870bebfb1d5    5 months ago      118MB

There is one last thing to add here: by default the buildDockerImage.sh script runs a md5sum checksum on the ORDS zip file just to make sure that the file is intact. You see this as the very first output of the build script. You can skip that checksum by passing on the -i option. In general there is no need to skip the checksum step, however, ORDS releases on a quarterly basis and it may be the case that the GitHub repo hasn't been updated with the latest checksum files yet. In such case you can still build your latest and greatest ORDS Docker image by bypassing the checksum via -i.

Now that you have an ORDS Docker image it's time to run an actual container of it. As ORDS is a REST server in front of an Oracle Database you will need an Oracle Database that ORDS can REST-enable for you. I already do have my Oracle Database Docker images on the same machine and so I will go ahead and REST-enable a database within a Docker container. However, I should point out that having an Oracle Database inside a Docker container is no requirement for running ORDS inside Docker! In fact, you can quite happily manage many Oracle databases with ORDS, regardless where your Oracle databases are running, Docker, locally, on a server, in the cloud, etc.

Setting Up the Docker Network

If your Oracle Database is not running inside a Docker container, you can skip this step!

Because the database and ORDS are both running within Docker I first have to setup a Docker network that these two containers can use to communicate with each other. Creating the network is easily done with just a simple command docker network create:

$ docker network create ords-database-network
b96c9fd9062f3aa0fb37db3dcd6319c6e3daefb99f52b82819e06f84b3ad38a0
$ docker network ls
NETWORK ID NAME DRIVER SCOPE
0cad4fa350c8 bridge bridge local
0e6f604bfce9 host host local
26709c337f2f none null local
b96c9fd9062f ords-database-network bridge local
$

Running an Oracle Database Docker Container

If your Oracle Database is not running inside a Docker container, you can skip this step! See Creating an Oracle Database Docker image for how to run Oracle Database in Docker.

Once you have the network defined you can now start a new Oracle Database container. The --network option in the docker run command will allow you to attach your database container to the Docker network:

$ docker run -d --name ords-db --network=ords-database-network -v /home/oracle/oradata:/opt/oracle/oradata oracle/database:12.2.0.1-ee
074e2e85ccdaf00d4ae5d93f56a2532154070a8f95083a343e78a753d748505b
$

Running an Oracle REST Data Services Docker Container

To run an ORDS Docker container you will have to know the following details:

  • ORACLE_HOST: Host on which the Oracle Database is running (default: localhost)
  • ORACLE_PORT: Port on which the Oracle Database is running (default: 1521)
  • ORACLE_SERVICE: Oracle Database service name that ORDS should connect to (default: ORCLPDB1)
  • ORACLE_PWD: SYS password of the Oracle Database
  • ORDS_PWD: ORDS user password you want to use
  • A volume where to store the ORDS configuration files in

Once you have all of these you can go ahead and run your ORDS Docker container via the docker run command.

Note: Because my database is also running inside Docker, I will have to specify the --network parameter in order to allow the two containers to communicate. The hostname for my database host inside the Docker network is the same as my Database Docker container name. I will therefore use -e ORACLE_HOST=ords-db.

If you do not have the Oracle Database running in Docker, you can skip the --network parameter!

$ docker run --name ords \
> -p 8888:8888 \
> --network=ords-database-network \
> -e ORACLE_HOST=ords-db \
> -e ORACLE_PORT=1521 \
> -e ORACLE_SERVICE=ORCLPDB1 \
> -e ORACLE_PWD=LetsDocker \
> -e ORDS_PWD=LetsORDS \
> -v /home/oracle/ords:/opt/oracle/ords/config/ords:rw \
> oracle/restdataservices:18.1.1
May 07, 2018 3:47:43 AM
INFO: Updated configurations: defaults, apex_pu
May 07, 2018 3:47:43 AM oracle.dbtools.installer.InstallerBase log
INFO: Installing Oracle REST Data Services version 18.1.1.95.1251
May 07, 2018 3:47:43 AM oracle.dbtools.installer.Runner log
INFO: ... Log file written to /opt/oracle/ords/logs/ords_install_core_2018-05-07_034743_00762.log
May 07, 2018 3:47:44 AM oracle.dbtools.installer.Runner log
INFO: ... Verified database prerequisites
May 07, 2018 3:47:45 AM oracle.dbtools.installer.Runner log
INFO: ... Created Oracle REST Data Services schema
May 07, 2018 3:47:45 AM oracle.dbtools.installer.Runner log
INFO: ... Created Oracle REST Data Services proxy user
May 07, 2018 3:47:45 AM oracle.dbtools.installer.Runner log
INFO: ... Granted privileges to Oracle REST Data Services
May 07, 2018 3:47:48 AM oracle.dbtools.installer.Runner log
INFO: ... Created Oracle REST Data Services database objects
May 07, 2018 3:47:56 AM oracle.dbtools.installer.Runner log
INFO: ... Log file written to /opt/oracle/ords/logs/ords_install_datamodel_2018-05-07_034756_00488.log
May 07, 2018 3:47:57 AM oracle.dbtools.installer.Runner log
INFO: ... Log file written to /opt/oracle/ords/logs/ords_install_apex_2018-05-07_034757_00832.log
May 07, 2018 3:47:59 AM oracle.dbtools.installer.InstallerBase log
INFO: Completed installation for Oracle REST Data Services version 18.1.1.95.1251. Elapsed time: 00:00:15.397

2018-05-07 03:48:00.688:INFO::main: Logging initialized @1507ms to org.eclipse.jetty.util.log.StdErrLog
May 07, 2018 3:48:00 AM
INFO: HTTP and HTTP/2 cleartext listening on port: 8888
May 07, 2018 3:48:00 AM
INFO: The document root is serving static resources located in: /opt/oracle/ords/doc_root
2018-05-07 03:48:01.505:INFO:oejs.Server:main: jetty-9.4.z-SNAPSHOT, build timestamp: 2017-11-21T21:27:37Z, git hash: 82b8fb23f757335bb3329d540ce37a2a2615f0a8
2018-05-07 03:48:01.524:INFO:oejs.session:main: DefaultSessionIdManager workerName=node0
2018-05-07 03:48:01.525:INFO:oejs.session:main: No SessionScavenger set, using defaults
2018-05-07 03:48:01.526:INFO:oejs.session:main: Scavenging every 600000ms
May 07, 2018 3:48:02 AM
INFO: Creating Pool:|apex|pu|
May 07, 2018 3:48:02 AM
INFO: Configuration properties for: |apex|pu|
cache.caching=false
cache.directory=/tmp/apex/cache
cache.duration=days
cache.expiration=7
cache.maxEntries=500
cache.monitorInterval=60
cache.procedureNameList=
cache.type=lru
db.hostname=ords-db
db.password=******
db.port=1521
db.servicename=ORCLPDB1
db.username=ORDS_PUBLIC_USER
debug.debugger=false
debug.printDebugToScreen=false
error.keepErrorMessages=true
error.maxEntries=50
jdbc.DriverType=thin
jdbc.InactivityTimeout=1800
jdbc.InitialLimit=3
jdbc.MaxConnectionReuseCount=1000
jdbc.MaxLimit=10
jdbc.MaxStatementsLimit=10
jdbc.MinLimit=1
jdbc.statementTimeout=900
log.logging=false
log.maxEntries=50
misc.compress=
misc.defaultPage=apex
security.disableDefaultExclusionList=false
security.maxEntries=2000

May 07, 2018 3:48:02 AM
WARNING: *** jdbc.MaxLimit in configuration |apex|pu| is using a value of 10, this setting may not be sized adequately for a production environment ***
May 07, 2018 3:48:02 AM
WARNING: *** jdbc.InitialLimit in configuration |apex|pu| is using a value of 3, this setting may not be sized adequately for a production environment ***
May 07, 2018 3:48:02 AM
INFO: Oracle REST Data Services initialized
Oracle REST Data Services version : 18.1.1.95.1251
Oracle REST Data Services server info: jetty/9.4.z-SNAPSHOT

2018-05-07 03:48:02.710:INFO:oejsh.ContextHandler:main: Started o.e.j.s.ServletContextHandler@48eff760{/ords,null,AVAILABLE}
2018-05-07 03:48:02.711:INFO:oejsh.ContextHandler:main: Started o.e.j.s.h.ContextHandler@402f32ff{/,null,AVAILABLE}
2018-05-07 03:48:02.711:INFO:oejsh.ContextHandler:main: Started o.e.j.s.h.ContextHandler@573f2bb1{/i,null,AVAILABLE}
2018-05-07 03:48:02.721:INFO:oejs.AbstractNCSARequestLog:main: Opened /tmp/ords_log/ords_2018_05_07.log
2018-05-07 03:48:02.755:INFO:oejs.AbstractConnector:main: Started ServerConnector@2aece37d{HTTP/1.1,[http/1.1, h2c]}{0.0.0.0:8888}
2018-05-07 03:48:02.755:INFO:oejs.Server:main: Started @3576ms

Now that ORDS is up and running, you can start REST-enabling your database. Note that all configuration files are within a volume, in my case -v /home/oracle/ords:/opt/oracle/ords/config/ords:rw. If you would like to change any of the ORDS configuration, you can just do so in the volume and then restart the container, if needed.

Docker (software) REST Web Protocols Database Oracle Database Data (computing) microservice

Published at DZone with permission of Gerald Venzl, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

Related

  • Building REST API Backend Easily With Ballerina Language
  • End-to-End REST Service Testing on Oracle Database
  • Jakarta Security and REST in the Cloud: Part 2 Getting to Know the Basics
  • Jakarta Security and REST in the Cloud Part 1: Hello World

Partner Resources

×

Comments
Oops! Something Went Wrong

The likes didn't load as expected. Please refresh the page and try again.

ABOUT US

  • About DZone
  • Support and feedback
  • Community research
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • support@dzone.com

Let's be friends:

Likes
There are no likes...yet! 👀
Be the first to like this post!
It looks like you're not logged in.
Sign in to see who liked this post!