Part 14: GCP: How to create docker container in GCP ?

In GCP, we can create a container for our application and can deploy it in five simple steps.

Lets have a look at these steps below.

I. Steps involved in creating Container

1. Code our Application
2. Dockerfile Creation
3. Build Container
4. Register our Container
5. Deploy and Run our Container

Here we will see the usage of Cloud Shell for this.

II. Understanding Basics
Lets understand few concepts involved in GCP below.

a. DockerFile – A file contains a set of commands to build the container automatically.
b. Cloud Shell – Its a lightweight VM preinstalled with utilities like docker, gcloud, etc.
c. Container Image – Image file of docker container containing the executable application code.
d. Registering Container – Saving container images on central online repository.
e. Cloud Deploy and Run – Completely GCP managed service to deploy and run our container online.

III. Activate Cloud Shell
We can activate cloud shell by clicking on below icon at top right corner below.


As soon as you click this, the shell will be activated and below screen is visible.


 

IV. Code our Application

saketalwar2@cloudshell:~ (second-abacus-334712)$ pwd
/home/saketalwar2

saketalwar2@cloudshell:~ (second-abacus-334712)$ mkdir ngelinux_gcp_docker

saketalwar2@cloudshell:~ (second-abacus-334712)$ ls
ngelinux_gcp_docker  README-cloudshell.txt

saketalwar2@cloudshell:~ (second-abacus-334712)$ cd ngelinux_gcp_docker
saketalwar2@cloudshell:~/ngelinux_gcp_docker (second-abacus-334712)$

saketalwar2@cloudshell:~/ngelinux_gcp_docker (second-abacus-334712)$ cat container1.py
import os

from flask import Flask

app=Flask(__name__)

@app.route('/')
def gcp_ngelinux():
    target = os.environ.get('TARGET', 'WELCOME TO NGELINUX')
    return format(target)

if __name__ == "__main__":
    app.run(debug=True,host='0.0.0.0',port=int(os.environ.get('PORT',8080)))
saketalwar2@cloudshell:~/ngelinux_gcp_docker (second-abacus-334712)$

Flask is the web interface that provides features to run this application on browser.

 

V. Creating DockerFile

saketalwar2@cloudshell:~/ngelinux_gcp_docker (second-abacus-334712)$ cat dockerfile
FROM python:3.7-slim

ENV CONT_HOME /app
WORKDIR $CONT_HOME
COPY . ./

RUN pip install Flask gunicorn

CMD exec gunicorn --bind :$PORT --workers 1 --threads 8 --timeout 0 app:app

saketalwar2@cloudshell:~/ngelinux_gcp_docker (second-abacus-334712)$

 

VI. Make files executable.

saketalwar2@cloudshell:~/ngelinux_gcp_docker (second-abacus-334712)$ ls -ltr
total 8
-rw-r--r-- 1 saketalwar2 saketalwar2 277 Dec 29 15:47 container1.py
-rw-r--r-- 1 saketalwar2 saketalwar2 180 Dec 29 16:08 dockerfile

### Make the files executable
saketalwar2@cloudshell:~/ngelinux_gcp_docker (second-abacus-334712)$ chmod +x *

saketalwar2@cloudshell:~/ngelinux_gcp_docker (second-abacus-334712)$ ls -ltr
total 8
-rwxr-xr-x 1 saketalwar2 saketalwar2 277 Dec 29 15:47 container1.py
-rwxr-xr-x 1 saketalwar2 saketalwar2 180 Dec 29 16:08 dockerfile
saketalwar2@cloudshell:~/ngelinux_gcp_docker (second-abacus-334712)$

 

VII. Building Container Image

saketalwar2@cloudshell:~/ngelinux_gcp_docker (second-abacus-334712)$ gcloud builds submit --tag gcr.io/second-abacus-334712/gcp_ngelinux
ERROR: (gcloud.builds.submit) Invalid value for [source]: Dockerfile required when specifying --tag

saketalwar2@cloudshell:~/ngelinux_gcp_docker (second-abacus-334712)$ mv dockerfile Dockerfile

saketalwar2@cloudshell:~/ngelinux_gcp_docker (second-abacus-334712)$ gcloud builds submit --tag gcr.io/second-abacus-334712/gcp_ngelinux
ERROR: (gcloud.builds.submit) You do not currently have an active account selected.
Please run:

  $ gcloud auth login

to obtain new credentials.

If you have already logged in with a different account:

    $ gcloud config set account ACCOUNT

to select an already authenticated account to use.

#### We need to authorize GCP for this. I have a GUI prompt appeared so i authorized in that.

saketalwar2@cloudshell:~/ngelinux_gcp_docker (second-abacus-334712)$ gcloud builds submit --tag gcr.io/second-abacus-334712/gcp_ngelinux
Creating temporary tarball archive of 3 file(s) totalling 12.4 KiB before compression.
Uploading tarball of [.] to [gs://second-abacus-334712_cloudbuild/source/1640794813.234216-2ad2b16c74484386a66caaa151440067.tgz]
API [cloudbuild.googleapis.com] not enabled on project [601986027583]. Would you like to enable and retry (this will take a few minutes)? (y/N)?  y

Enabling service [cloudbuild.googleapis.com] on project [601986027583]...
Operation "operations/acf.p2-601986027583-cce8fe3d-5d8e-4e8d-8abd-bfae09738c56" finished successfully.
Created [https://cloudbuild.googleapis.com/v1/projects/second-abacus-334712/locations/global/builds/6d6d5f04-30b6-4ae4-a508-d80bf22369f2].
Logs are available at [https://console.cloud.google.com/cloud-build/builds/6d6d5f04-30b6-4ae4-a508-d80bf22369f2?project=601986027583].
--------------------------------------------------------------------- REMOTE BUILD OUTPUT ---------------------------------------------------------------------
starting build "6d6d5f04-30b6-4ae4-a508-d80bf22369f2"

FETCHSOURCE
Fetching storage object: gs://second-abacus-334712_cloudbuild/source/1640794813.234216-2ad2b16c74484386a66caaa151440067.tgz#1640794815734604
Copying gs://second-abacus-334712_cloudbuild/source/1640794813.234216-2ad2b16c74484386a66caaa151440067.tgz#1640794815734604...
/ [1 files][  751.0 B/  751.0 B]
Operation completed over 1 objects/751.0 B.
BUILD
Already have image (with digest): gcr.io/cloud-builders/docker
Sending build context to Docker daemon  15.87kB
Step 1/6 : FROM python:3.7-slim
3.7-slim: Pulling from library/python
a2abf6c4d29d: Pulling fs layer
625294dad115: Pulling fs layer
2d55109ef858: Pulling fs layer
8f7394e7143f: Pulling fs layer
8571408494af: Pulling fs layer
8f7394e7143f: Waiting
8571408494af: Waiting
625294dad115: Download complete
8f7394e7143f: Verifying Checksum
8f7394e7143f: Download complete
2d55109ef858: Verifying Checksum
2d55109ef858: Download complete
a2abf6c4d29d: Verifying Checksum
a2abf6c4d29d: Download complete
8571408494af: Download complete
a2abf6c4d29d: Pull complete
625294dad115: Pull complete
2d55109ef858: Pull complete
8f7394e7143f: Pull complete
8571408494af: Pull complete
Digest: sha256:f7f072342e7c29b0fb035057368dfdce5221550c48aa5421bafed0ad1da5a435
Status: Downloaded newer image for python:3.7-slim
 d3c9ad326043
Step 2/6 : ENV CONT_HOME /app
 Running in 8918d3102af0
Removing intermediate container 8918d3102af0
 424e0c9de10a
Step 3/6 : WORKDIR $CONT_HOME
 Running in 5e7ddc0311fd
Removing intermediate container 5e7ddc0311fd
 41f5b8a827ff
Step 4/6 : COPY . ./
 1317bf6055bb
Step 5/6 : RUN pip install Flask gunicorn
 Running in 3346a9bffe41
Collecting Flask
  Downloading Flask-2.0.2-py3-none-any.whl (95 kB)
Collecting gunicorn
  Downloading gunicorn-20.1.0-py3-none-any.whl (79 kB)
Collecting itsdangerous>=2.0
  Downloading itsdangerous-2.0.1-py3-none-any.whl (18 kB)
Collecting click>=7.1.2
  Downloading click-8.0.3-py3-none-any.whl (97 kB)
Collecting Jinja2>=3.0
  Downloading Jinja2-3.0.3-py3-none-any.whl (133 kB)
Collecting Werkzeug>=2.0
  Downloading Werkzeug-2.0.2-py3-none-any.whl (288 kB)
Requirement already satisfied: setuptools>=3.0 in /usr/local/lib/python3.7/site-packages (from gunicorn) (57.5.0)
Collecting importlib-metadata
  Downloading importlib_metadata-4.10.0-py3-none-any.whl (17 kB)
Collecting MarkupSafe>=2.0
  Downloading MarkupSafe-2.0.1-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl (31 kB)
Collecting typing-extensions>=3.6.4
  Downloading typing_extensions-4.0.1-py3-none-any.whl (22 kB)
Collecting zipp>=0.5
  Downloading zipp-3.6.0-py3-none-any.whl (5.3 kB)
Installing collected packages: zipp, typing-extensions, MarkupSafe, importlib-metadata, Werkzeug, Jinja2, itsdangerous, click, gunicorn, Flask
Successfully installed Flask-2.0.2 Jinja2-3.0.3 MarkupSafe-2.0.1 Werkzeug-2.0.2 click-8.0.3 gunicorn-20.1.0 importlib-metadata-4.10.0 itsdangerous-2.0.1 typing-extensions-4.0.1 zipp-3.6.0
WARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv
WARNING: You are using pip version 21.2.4; however, version 21.3.1 is available.
You should consider upgrading via the '/usr/local/bin/python -m pip install --upgrade pip' command.
Removing intermediate container 3346a9bffe41
 3e1589d4a0d1
Step 6/6 : CMD exec gunicorn --bind :$PORT --workers 1 --threads 8 --timeout 0 app:app
 Running in d8f258b25091
Removing intermediate container d8f258b25091
 64f624e68e9e
Successfully built 64f624e68e9e
Successfully tagged gcr.io/second-abacus-334712/gcp_ngelinux:latest
PUSH
Pushing gcr.io/second-abacus-334712/gcp_ngelinux
The push refers to repository [gcr.io/second-abacus-334712/gcp_ngelinux]
2d256058bb2b: Preparing
c0f2abe34197: Preparing
2ef0a9581e5a: Preparing
25ad0307b4c1: Preparing
874b45955cb1: Preparing
85c923303735: Preparing
d0fa20bfdce7: Preparing
2edcec3590a4: Preparing
85c923303735: Waiting
d0fa20bfdce7: Waiting
2edcec3590a4: Waiting
874b45955cb1: Layer already exists
25ad0307b4c1: Layer already exists
85c923303735: Layer already exists
d0fa20bfdce7: Layer already exists
2edcec3590a4: Layer already exists
c0f2abe34197: Pushed
2ef0a9581e5a: Pushed
2d256058bb2b: Pushed

latest: digest: sha256:bb695af31f42bb97ffe7e04b6b00ee7d7e0a3ec0ab40e3c7542e5d49fe28f849 size: 1995
DONE
---------------------------------------------------------------------------------------------------------------------------------------------------------------
ID: 6d6d5f04-30b6-4ae4-a508-d80bf22369f2
CREATE_TIME: 2021-12-29T16:20:34+00:00
DURATION: 25S
SOURCE: gs://second-abacus-334712_cloudbuild/source/1640794813.234216-2ad2b16c74484386a66caaa151440067.tgz
IMAGES: gcr.io/second-abacus-334712/gcp_ngelinux (+1 more)
STATUS: SUCCESS
saketalwar2@cloudshell:~/ngelinux_gcp_docker (second-abacus-334712)$

 

VIII. Verify the gs i.e. Google Cloud Storage if new bucket is created and new app is created there.


Here you can see the new bucket is created.

 

IX. Now deploy and run our new Application tar file created.

saketalwar2@cloudshell:~ (second-abacus-334712)$ cd ngelinux_gcp_docker/
saketalwar2@cloudshell:~/ngelinux_gcp_docker (second-abacus-334712)$ ls -ltr
total 8
-rwxr-xr-x 1 saketalwar2 saketalwar2 277 Dec 29 15:47 container1.py
-rwxr-xr-x 1 saketalwar2 saketalwar2 180 Dec 29 16:08 Dockerfile
saketalwar2@cloudshell:~/ngelinux_gcp_docker (second-abacus-334712)$

saketalwar2@cloudshell:~/ngelinux_gcp_docker (second-abacus-334712)$ gcloud run deploy --image gcr.io/second-abacus-334712/gcp_ngelinux
Service name (gcpngelinux):
Please specify a region:
[1] asia-east1
[2] asia-east2
[3] asia-northeast1
[4] asia-northeast2
[5] asia-northeast3
[6] asia-south1
[7] asia-south2
[8] asia-southeast1
[9] asia-southeast2
[10] australia-southeast1
[11] australia-southeast2
[12] europe-central2
[13] europe-north1
[14] europe-west1
[15] europe-west2
[16] europe-west3
[17] europe-west4
[18] europe-west6
[19] northamerica-northeast1
[20] northamerica-northeast2
[21] southamerica-east1
[22] southamerica-west1
[23] us-central1
[24] us-east1
[25] us-east4
[26] us-west1
[27] us-west2
[28] us-west3
[29] us-west4
[30] cancel
Please enter your numeric choice: 1

To make this the default region, run `gcloud config set run/region asia-east1`.

Allow unauthenticated invocations to [gcpngelinux] (y/N)? y

Deploying container to Cloud Run service [gcpngelinux] in project [second-abacus-334712] region [asia-east1]
OK Deploying new service... Done.
OK Creating Revision... Initializing project for the current region.
OK Routing traffic...
OK Setting IAM Policy...
Done.
Service [gcpngelinux] revision [gcpngelinux-00001-xaq] has been deployed and is serving 100 percent of traffic.
Service URL: https://gcpngelinux-2n2cfvtw3q-de.a.run.app
saketalwar2@cloudshell:~/ngelinux_gcp_docker (second-abacus-334712)$

 

X. Now you can visit the above URL for our application to see its running.

https://gcpngelinux-2n2cfvtw3q-de.a.run.app/


Leave a Reply

Your email address will not be published.