How to Dockerize a Python Barcode Reader for ARM64 Devices
Among the Python barcode SDKs available, only a few ship native ARM64 support. The Dynamsoft Barcode Reader dynamsoft-barcode-reader-bundle package stands out, offering robust 1D and 2D barcode recognition for ARM64 devices. This article guides you through creating an ARM64 emulated environment on Windows, enabling seamless barcode scanning implementation with the Dynamsoft Python Barcode SDK.
This article is Part 7 in a 8-Part Series.
- Part 1 - Build a Python GUI Barcode Scanner on Raspberry Pi with Qt PySide6
- Part 2 - How to Build a Cross-Platform GUI Python Barcode and QR Code Reader with PySide6 and Qt Designer
- Part 3 - How to Read QR Codes from Screen Capture in Python with Qt and Dynamsoft Barcode SDK
- Part 4 - How to Integrate a Barcode Scanner in a Django Web App with Python
- Part 5 - How to Build a Python Flet Chat App with Barcode Scanning and Gemini AI
- Part 6 - Python Ctypes: Call a C++ Shared Library Without Building Any C++ Code
- Part 7 - How to Dockerize a Python Barcode Reader for ARM64 Devices
- Part 8 - ZXing vs ZBar vs Dynamsoft: Python Barcode Reader Comparison with Accuracy and Speed Benchmarks
What you’ll build: A complete Docker-based development environment for running Python barcode and QR code recognition on ARM64 (Raspberry Pi, Jetson) using the Dynamsoft Barcode Reader bundle.
Key Takeaways
- The
dynamsoft-barcode-reader-bundlepackage (11.6.4000) ships prebuilt aarch64 wheels, so barcode recognition runs natively inside ARM64 Docker containers. - You can emulate an ARM64 environment on Windows using QEMU and Docker, eliminating the need for physical Raspberry Pi or Jetson hardware during development.
- Use
--cpuset-cpusto simulate limited CPU cores in Docker and benchmark barcode decoding performance under constrained hardware conditions. - The PIL + NumPy decoding workflow keeps the container image light; OpenCV is available too, since it also publishes aarch64 wheels.
Common Developer Questions
How do I run a Python barcode scanner in a Docker container on ARM64?
Build an ARM64-targeted Docker image that installs dynamsoft-barcode-reader-bundle, then run your barcode script inside that container with --platform linux/arm64. That gives you a reproducible ARM64 barcode environment even on a non-ARM development machine.
Can I emulate a Raspberry Pi or Jetson ARM64 architecture on Windows for barcode SDK testing?
Yes. The article uses Docker plus QEMU-based emulation on Windows so you can build and test ARM64 images without having physical hardware beside you. That is especially useful for validating dependency installation and barcode workflow logic before deploying to embedded boards.
How do I limit Docker container CPU to simulate embedded device performance?
Use –cpuset-cpus to simulate limited CPU cores in Docker and benchmark barcode decoding performance under constrained hardware conditions. Additionally, multiarch/qemu-user-static is a Docker image that integrates with QEMU, enabling emulation of different CPU architectures within Docker containers.
Set Up the Dynamsoft Python Barcode SDK
To get started, you can easily install the Dynamsoft Python Barcode SDK via pip:
pip install dynamsoft-barcode-reader-bundle==11.6.4000
The SDK supports Python 3.10 to 3.14.
Supported Platforms
- Windows (x64)
- Linux (x64 and ARM64)
- macOS (x64 and ARM64)
License Key Activation
After installation, you will need a license key to activate the SDK. Get a 30-day free trial license for Dynamsoft Barcode Reader.
from dynamsoft_barcode_reader_bundle import *
error_code, error_message = LicenseManager.init_license(
"LICENSE-KEY")
Run a Quick Barcode Scan
Here’s a simple example to get you up and running quickly:
from dynamsoft_barcode_reader_bundle import *
license_key = "LICENSE-KEY"
image = r"PATH-TO-IMAGE"
error_code, error_message = LicenseManager.init_license(license_key)
if error_code != EnumErrorCode.EC_OK and error_code != EnumErrorCode.EC_LICENSE_CACHE_USED:
print("License initialization failed: ErrorCode:",
error_code, ", ErrorString:", error_message)
else:
cvr_instance = CaptureVisionRouter()
result = cvr_instance.capture(image, EnumPresetTemplate.PT_READ_BARCODES.value)
if result.get_error_code() != EnumErrorCode.EC_OK:
print("Error:", result.get_error_code(),
result.get_error_string())
else:
items = result.get_items()
print('Found {} barcodes.'.format(len(items)))
for item in items:
format_type = item.get_format_string()
text = item.get_text()
print("Barcode Format:", format_type)
print("Barcode Text:", text)
print("-------------")
Additional Resources
- Sample Code: Explore more examples on GitHub at Dynamsoft Barcode Reader Python Samples
- Online API Documentation: Visit the official documentation
- Visual Studio Code Extension: Enhance your development experience with the Dynamsoft Barcode Reader extension for Visual Studio Code.
Why Use Docker to Emulate ARM64 Architecture
Creating a Python barcode scanning application for ARM64 devices, such as a Raspberry Pi or Jetson, is made easier with emulated environments. These environments allow you to develop and test your code without the immediate need for physical ARM hardware, providing a flexible and convenient development workflow.
Build a Docker ARM64 Image with the Dynamsoft Barcode SDK
To emulate the ARM architecture on a Windows machine, you can leverage QEMU, a popular open-source emulator. Additionally, multiarch/qemu-user-static is a Docker image that integrates with QEMU, enabling emulation of different CPU architectures within Docker containers.
Follow these steps to create a Docker ARM64 image with the Dynamsoft Barcode SDK on Windows:
- Install Docker Desktop for Windows: Start by installing Docker Desktop on your Windows machine.
-
Set Up QEMU for Cross-Platform Emulation: Install qemu-user-static:
docker run --rm --privileged multiarch/qemu-user-static:register --reset -
Create a Dockerfile for ARM64: Write a Dockerfile that uses an ARM64 base image and installs the Dynamsoft Barcode Reader bundle, OpenCV, and Pillow.
DockerfileArm64
FROM arm64v8/python RUN apt-get update && apt-get install -y libgl1 libglib2.0-0 RUN pip install dynamsoft-barcode-reader-bundle==11.6.4000 opencv-python pillowNote:
libgl1andlibglib2.0-0are the runtime libraries OpenCV needs on current Debian-based images. If you only use the Pillow workflow shown below, you can dropopencv-pythonfrom the pip line and skip the apt packages entirely. -
Build the Docker Image for ARM64: Build the Docker image:
docker build --platform linux/arm64 -f DockerfileArm64 -t <IMAGE-NAME> .
With these steps, you have successfully created a Docker ARM64 image containing the Dynamsoft Python Barcode SDK. You can now proceed to write and run a barcode reader script within the container.
Run Python Barcode Recognition in an ARM64 Docker Container
Single-board computers like Raspberry Pi and Jetson often lack high-end hardware, which may impact barcode decoding speed for large images. A typical use case involves capturing low-resolution images (e.g., 640x480) from a USB camera and decoding QR codes in real-time.
Here’s how to simulate this process:
Capture and Decode Barcode Images from a USB Camera
Use the following Python script to capture frames from a USB camera and decode barcodes in real time:
import cv2
from dynamsoft_barcode_reader_bundle import *
import numpy as np
capture = cv2.VideoCapture(0)
if not capture.isOpened():
print("Cannot open camera")
exit()
error_code, error_message = LicenseManager.init_license(
"DLS2eyJoYW5kc2hha2VDb2RlIjoiMjAwMDAxLTE2NDk4Mjk3OTI2MzUiLCJvcmdhbml6YXRpb25JRCI6IjIwMDAwMSIsInNlc3Npb25QYXNzd29yZCI6IndTcGR6Vm05WDJrcEQ5YUoifQ==")
if error_code != EnumErrorCode.EC_OK and error_code != EnumErrorCode.EC_LICENSE_CACHE_USED:
print("License initialization failed: ErrorCode:",
error_code, ", ErrorString:", error_message)
else:
cvr_instance = CaptureVisionRouter()
index = 0
while True:
ret, frame = capture.read()
if cv2.waitKey(1) == ord('q'):
break
result = cvr_instance.capture(
frame, EnumPresetTemplate.PT_READ_BARCODES.value)
if result.get_error_code() != EnumErrorCode.EC_OK:
print("Error:", result.get_error_code(),
result.get_error_string())
else:
items = result.get_items()
print('Found {} barcodes.'.format(len(items)))
for item in items:
format_type = item.get_format_string()
text = item.get_text()
print("Barcode Format:", format_type)
print("Barcode Text:", text)
location = item.get_location()
x1 = location.points[0].x
y1 = location.points[0].y
x2 = location.points[1].x
y2 = location.points[1].y
x3 = location.points[2].x
y3 = location.points[2].y
x4 = location.points[3].x
y4 = location.points[3].y
print("Location Points:")
print("({}, {})".format(x1, y1))
print("({}, {})".format(x2, y2))
print("({}, {})".format(x3, y3))
print("({}, {})".format(x4, y4))
print("-------------------------------------------------")
pts = np.array([(x1, y1), (x2, y2), (x3, y3), (x4, y4)], np.int32)
pts = pts.reshape((-1, 1, 2))
cv2.drawContours(frame, [pts], 0, (0, 255, 0), 2)
cv2.putText(frame, text, (x1, y1 - 10),
cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0, 255), 2)
cv2.imshow(
"Original Image with Detected Barcodes", frame)
cv2.destroyAllWindows()
Decode Captured Barcode Images with PIL
Next, use the following script to read a folder of saved images using PIL and decode them with Dynamsoft Barcode Reader. The image folder can be passed as a command-line argument; when omitted, the script looks for the repository’s images folder:
import os
import sys
import time
from PIL import Image
from dynamsoft_barcode_reader_bundle import *
import numpy as np
def main():
error_code, error_message = LicenseManager.init_license(
"DLS2eyJoYW5kc2hha2VDb2RlIjoiMjAwMDAxLTE2NDk4Mjk3OTI2MzUiLCJvcmdhbml6YXRpb25JRCI6IjIwMDAwMSIsInNlc3Npb25QYXNzd29yZCI6IndTcGR6Vm05WDJrcEQ5YUoifQ==")
if error_code != EnumErrorCode.EC_OK and error_code != EnumErrorCode.EC_LICENSE_CACHE_USED:
print("License initialization failed: ErrorCode:",
error_code, ", ErrorString:", error_message)
# read file list
if len(sys.argv) > 1:
target_dir = os.path.abspath(sys.argv[1])
else:
target_dir = os.path.normpath(os.path.join(
os.path.dirname(os.path.abspath(__file__)), '..', '..', '..', 'images'))
print(target_dir)
cvr_instance = CaptureVisionRouter()
if os.path.exists(target_dir):
filelist = os.listdir(target_dir)
index = 0
while index < len(filelist):
file = filelist[index]
filapath = os.path.join(target_dir, file)
index += 1
if os.path.isfile(filapath):
with Image.open(filapath) as im:
try:
start_time = time.time()
img_array = np.array(im)
result = cvr_instance.capture(img_array, EnumPresetTemplate.PT_READ_BARCODES.value)
elapsed_time = time.time() - start_time
print(file + ", elapsed time: " + str(round(elapsed_time *
1000)) + "ms, " + ' results: ' + str(len(result.get_items())))
if result.get_error_code() != EnumErrorCode.EC_OK:
print("Error:", result.get_error_code(),
result.get_error_string())
else:
items = result.get_items()
print('Found {} barcodes.'.format(len(items)))
for item in items:
format_type = item.get_format_string()
text = item.get_text()
print("Barcode Format:", format_type)
print("Barcode Text:", text)
print("-------------------------------------------------")
except Exception as err:
print(err)
print('-------------------------------------')
if __name__ == '__main__':
main()
Run the Barcode Script Inside the Docker Container
Mount the current folder to the Docker container and run the script. Pass the folder that holds your captured images as the script argument:
docker run --platform linux/arm64 -it --rm -v $(pwd):/usr/src/myapp -w /usr/src/myapp <IMAGE-NAME> python pillow_test.py /usr/src/myapp/images
If your images live in the mounted folder itself, use . as the argument.
Limit CPU Resources to Simulate Embedded Hardware
One critical factor to consider when running barcode decoding tasks in Docker containers is the impact of CPU resources on performance.

By default, Docker containers have unrestricted access to the host machine’s CPU cycles, which means they can use as many CPU resources as needed.

However, if you want to control and test the performance of your application under specific conditions, Docker allows you to limit the number of CPU cores available to a container using the –cpuset-cpus option. This can be useful for simulating scenarios where your application runs on hardware with limited processing power.
For instance, you can restrict the container to use only two CPU cores and observe how this affects the decoding speed:
docker run --cpuset-cpus="0,1" --platform linux/arm64 -it --rm -v $(pwd):/usr/src/myapp -w /usr/src/myapp <IMAGE-NAME> python pillow_test.py /usr/src/myapp/images
To verify the number of CPU cores available to the container, you can use the nproc command:
docker run --cpuset-cpus="0,1" --platform linux/arm64 -it --rm -v $(pwd):/usr/src/myapp -w /usr/src/myapp <IMAGE-NAME> nproc
2
In this example, the command should return 2, confirming that the container is limited to two CPU cores.
Emulate Raspberry Pi Hardware with DockerPi
For a more realistic emulation, use dockerpi to simulate a Raspberry Pi:
docker run -it lukechilds/dockerpi pi3
pi@raspberrypi:~$ lscpu
Architecture: aarch64
Byte Order: Little Endian
CPU(s): 4
On-line CPU(s) list: 0-3
Thread(s) per core: 1
Core(s) per socket: 4
Socket(s): 1
Vendor ID: ARM
Model: 4
Model name: Cortex-A53
Stepping: r0p4
CPU max MHz: 700.0000
CPU min MHz: 700.0000
BogoMIPS: 125.00
Flags: fp asimd evtstrm aes pmull sha1 sha2 crc32 cpuid
Common Issues and Edge Cases
- The bundle has no ARM32 (armv7) wheels:
dynamsoft-barcode-reader-bundlepublishes aarch64 and x86_64 wheels only. Use a 64-bit base image such asarm64v8/python; 32-bit images likearm32v7/pythonwill fail atpip install. - QEMU emulation is significantly slower than native hardware: Barcode decoding times under QEMU can be 5–10x slower than on real ARM devices. Use emulated environments for functional testing only — benchmark on actual hardware for production performance data.
- Docker
--platformflag not recognized: Ensure Docker Desktop has experimental features enabled and that you have rundocker run --rm --privileged multiarch/qemu-user-static:register --resetto register QEMU interpreters before building cross-platform images.