In this howto article we are debugging a python application running inside a container. The goal is to equip developers to troubleshoot instances running in any production environment, regardless of the platform. We focus at what needs to be done at the container level as well as at the debugger client level (VS code).
The complete setup requires an Access Gateway. We presume it is already setup. You can find information on how the access works as well as how to setup the gateway here.
See this page for a high level discussion about the noah solution.
The container image is built as usual but with 2 additional elements.
First, 2 executable binaries are added to the image. They are the NearEDGE Access agent (called noah agent) and a small optional start helper.
Second, noah agent must be started, optionally with the help of the helper.
Here is a sample Dockerfile. We get the chainstart and noah binaries from the image that NearEDGE provides to your organization.
#
# Get the noah agent
#
# Use the repository specific to YOUR organization - Below is
# just an example
FROM <image> as noah
#
# Test project (final container image)
#
# Use whatever base image suitable for your application.
FROM python:latest
RUN pip3 install flask debugpy
# Remote access is provided by noah
RUN mkdir /noah
COPY --from=noah /opt/thor/chainstart /opt/chainstart
COPY --from=noah /opt/thor/noah /opt/noah
# Actual application
COPY app.py /opt/demo/
#
# Start noah and the demo python code - Using chainstart
#
ENTRYPOINT ["/opt/chainstart", \
"--", "/opt/noah", "--dataloc", "/noah", \
"--", "/usr/local/bin/python3", "-m", "debugpy", \
"--listen", "127.0.0.1:12345", "--wait-for-client", \
"/opt/demo/app.py"]<image> is the noah image specific to your organization.
We use chainstart to start both the noah agent as well as the application. You can use other means, such as a bash script, as you see fit. Make sure to start noah with the correct argument(s).
The application itself it started under the debugpy module, which is configured to wait for the debugger client. You can remove wait-for-client to start immediately your application while still being able to attach from the client.
You probably normally start the container using an automation or CI/CD compatible method. If you want to manually start the container, do the following:
docker run \
--detach \
--volume <uniquename>:/noah \
-p 8000:8000 \
--name <name> \
<image>:latestNote that the debugpy port is NOT exposed.
<uniquename> identifies a persisten volume where noah stores its information.
<name> is just a name for the container instance. Use what ever suits you.
<image> is the image you created with your nodeJS application.
You can find more information on starting containers that include noah. See this guide
Note that debugpy only listens on the local interface since this is where the noah agent forwards the client requests to. This results in debugpy being only accessible from within the container and is a good thing. This is part of the security benefits provided by noah.
Contrary to other solutions, such as using SSH, or a VPN, noah never exposes more than just the internal of a running container instance. In particular, the host where the container runs remains unaccessible to the user of noah.
To demonstrate the client side of debugging a containerized python application we are using this simple application.
from flask import Flask
app = Flask(__name__)
@app.route('/')
def hello():
return "Hello World!\n"
if __name__ == '__main__':
app.run(host='0.0.0.0', port=8000)
NoneThe launch configuration simply needs to point at the DNS name corresponding to container instance. In the following launch.json file, 2 configurations are defined; 1 for debugging on the local workstation and 1 to debug a production instance.
{
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "Python: Current File",
"type": "python",
"request": "launch",
"program": "${file}",
"console": "integratedTerminal",
"justMyCode": true
},
{
"name": "Python: Attach to Remote Container",
"type": "python",
"request": "attach",
"host": "demopythoncontaIner.ap2zone.nearedge-it.com", // replace this with the alias and DNS domain you defined
"port": 12345, // Must match how the configuration in debugpy
"pathMappings": [
{
"localRoot": "${workspaceFolder}",
"remoteRoot": "/opt/demo"
}
]
}
]
}We saw how to instrument the container image by adding the noah agent to it. We also saw how to start 2 applications in the container by using the additional chainstart application and started the python application under the VS code debugpy module. Finally, we saw how to setup VS code for remote debugging.
We also saw that the overall security of the production platform is never compromised when using noah.
See the Microsoft Web site for more information on using VS code. See this page that describes the SSH method, which served as the basis for this howto.