Monday, 7 October 2019

Packaging Ruby Code for AWS with Native Extensions

Back in November 2018, AWS announced support for running Ruby code in AWS Lambda.

AWS provides advice on how to package your Ruby code to deploy it as a Lambda function, and assuming a project laid out like this...
...the advice is as simple as:
  1. run bundle install
  2. zip up everything

As a build script, this could be:
set -euo pipefail
bundle install --deployment --path vendor/bundle --without development
zip -qr *.rb vendor

This works fine for trivial applications, but when your function contains gems with native extensions, we need to take a more sophisticated approach.

The lambda ruby runtime

When using gems with native extensions, the native extensions need to be compiled to be compatible with the configuration of the ruby runtime where these gems will be used.

The configuration of the ruby runtime you have installed on your development machine or CI/CD server probably doesn't match the runtime used by the AWS Lambda service, because it's likely to have been configured differently at build time.

lambci/lambda docker images

Fortunately, the lambci/lambda docker images are built from production AWS Lambda instances to mimic the production AWS Lambda runtimes in a docker container. These images are also used by Amazon's own SAM command line tool to run lambda functions locally.

These images are also available in build variants that are pre-configured with tools such as gcc that are needed to build native extensions.

A better build script

Using docker and the lambci images, we can create a better build script that leverages docker to ensure that native extensions are built in a way that is compatible with the AWS Lambda runtime.

First, we add a Dockerfile to the root of the project:
FROM lambci/lambda:build-ruby2.5
RUN chown 1000 /var/task

USER 1000

WORKDIR /var/task

COPY Gemfile Gemfile.lock /var/task/

RUN bundle install --deployment --path vendor/bundle --without development

COPY *.rb /var/task/

When built, this Dockerfile will configure an image containing your lambda code, and it's required gems, built to be compatible with the AWS Lambda runtime, using the lambci/lamba:build-ruby2.5 image as a base.

Now we adjust the build script to build the docker image and zip up the files from within the image:
set -euo pipefail
docker build --tag my-lambda-image .
docker run --volume "$PWD:/src" --workdir /var/task --user "$UID:$GROUPS" --rm my-lambda-image sh -c "zip -qr /src/ *.rb vendor"
This builds an image based on the Dockerfile above, then executes the zip command from within a container using that image.

The result is a zip file ( that contains the ruby code and all gems required for deployment to AWS Lambda.

Notes about the Dockerfile

  1. Most steps are performed as a non-root user, because bundle install does not like being run as root. The actual user id used is not important as all ownership information is lost when the zip file is created.
  2. Rather than copying all the source code into the container, the Gemfile and Gemfile.lock files only are copied in first, then bundle install is run. Doing this enables docker to cache the build steps all the way to the final COPY command if the Gemfile and Gemfile.lock files have not changed. This reduces the build cycle time greatly if the source code is changing, but the required gems are not.


The lambci/lambda docker images can be used to provide a build environment that closely mimics the actual AWS Lambda runtime.

These can be used in a build script to ensure that gems with native extensions are built in a way that is compatible with the AWS Lambda runtime.

The Dockerfile leverages docker's build caching system to allow the lengthy bundle install step to be skipped when the set of required gems have not changed.

Saturday, 5 January 2013

Home-made solder paste stencil

SMD solder paste stencils are used to accurately "print" a thin layer of solder paste onto a PCB on which the components are placed before reflow soldering. The "printing" is done in a method similar to screen printing, where the solder paste is squeegeed through a 4 mil thick, stainless steel stencil onto the PCB.

This is all well and good, but commercial stencils are expensive, and are massive overkill for prototype boards. Here is a method for producing a "good-enough" stencil using aluminium sheet via a method similar to PCB production via the UV photosensitive film method.


  • Aluminium sheet, preferably 4/1000 inch (4 mil) thick.
    I've sourced mine from an aluminium BBQ tray from my favourite shop, the Reject Shop. It's not quite 4 mil thick, but it's much thicker than "foil". Cut a flat section from the bottom at least as big as your PCB, very carefully with scissors.
  • UV Photosensitive film.
    This is the same film as used for PCB production in my previous posts.
  • Ferric Chloride solution.
    Yep, the same stuff you might use to etch copper off a PCB. I've got a very old bottle of solution, from back when Dick Smith actually sold things like this.
  • A transparency printed with the solder paste pattern you want to achieve.
    This is the same as for PCB production, but you want a positive, not a negative. This is, ink where you want the paste to go.


Bond the UV sensitive film to one side of the aluminium sheet - this is the same procedure as for PCBs
Cover the other side of the aluminium sheet in a waterproof adhesive tape. I used clear packing tape, which in retrospect was too sticky, as it was hard to remove and caused folds in the sheet when removing. An alternative here may be to apply spray paint. Make sure the entire surface is covered, go around the edges if possible.
Expose the film on the sheet to UV light through the transparency - same procedure as for PCBs again.
"Develop" the film - same process as PCBs again.
You should have something like this at this point:
0805's and SOT-23's and one wide SOIC 20. All aluminium covered except where the paste is to go 
Next, place the sheet in a dilute solution of ferric chloride. I used a mix of about 50/50 water and ferric chloride. Warning: Aluminium reacts very strongly with ferric chloride. Take care!
After 20 minutes of lightly brushing the reacting surfaces in the etchant, it should look like this:
Exposed aluminium etched right through the sheet.
Now remove the tape. This turned out to be hard to do without damaging the stencil. Eucalyptus oil helps to "unstick" the tape.
Final stencil, rear side.
That's it - the stencil is ready for use.


There are two uses for this stencil:
  1. As a stencil for where you DON'T want to apply protective lacquer to your copper board.
    Just use the stencil to put down a thin layer of petroleum jelly instead of solder paste, then apply spray circuit lacquer to the board. Once dry, wash the petroleum jelly off with methylated spirit. You will be left with the board protected by the lacquer, except where the solder paste is to go. This will help prevent the paste from flowing down the tracks of the copper board (effectively, a solder mask)
  2. As a solder paste stencil.
    I found using a plastic squeegee, like a credit card to be ideal for spreading the paste. Here's the result:
Solder paste applied with stencil
And the re-flowed board:
Re-flowed using hot air


Overall, reasonably successful. I was surprised how well the aluminium sheet retained the small fillets between the openings.
Things to watch out for next time:
  • Protect the rear side of the aluminium sheet with something other than clear packing tape. The removal of the tape almost ruined the stencil
  • Find some slightly thicker sheet - the amount of paste left on the board was bordering on the "too little" side. I saw a real nice looking BBQ tray at Woolworths the other day that felt just a little thicker.
  • Don't reflow with hot air, or next time, turn down the flow. The air caused the 0806 resistors to blow around once the paste became liquid. They did capillary into place nice and straight at first.

Saturday, 17 November 2012

Bubble etch tank complete

All the ebay ordered parts have arrived, and so I've assembled the etch tank. It all went together as planned in the last post - the only tricky detail was cutting some plastic strips to cover the hole where the semi-circular stand holder was removed from the inside of the frame.
Etch tank bubbles at 51 degrees
On the right is the aquarium air pump. This is connected to the air curtain, cut to length and sitting at the bottom of the tank. A right-angled connector for the air curtain was made from a scrap of polyethylene (aka, blue plastic chopping board) and the barb from a garden irrigation tube joiner. And a bit of hot-melt glue.

The multimeter is showing the temperature (Celsius) of the water in the tank, via the thermocouple in the tank top centre.

The water is heated by that white stick sitting vertically in the left of the tank - this is the heater - just two 30 ohm resistors in series, encased in heatshrink tubing.

The heater seems pretty effective. At 0.75A of current, I was able to raise the water temperature from 22 to 52 degrees in about 15 minutes, so it should be more than capable of maintaining the temperature of the etching solution, if it starts at the correct temperature. I'm driving the heater from an adjustable bench supply, so I'll adjust the current to find the equilibrium point is (or near enough).

Now, all I need is a project to etch...

Total cost

2"FORMAT" 6x8" photo frames$6.00
1Small tube of silicone sealant$8.50
1Aquarium air pump (incl delivery)$6.58
12 metre length of air tubing (incl delivery)$2.45
130cm air curtain (incl delivery)$1.96
230 ohm, 6 Watt wirewound resistors$3.68
1Length of heatshrink tubing-
1Length wire for heater-
Total:     $29.17

Friday, 19 October 2012

Heated Bubble Etch Tank...How Cheap?

Next up, I'm going to try and make a PCB etching tank, as cheaply as possible. The low-cost bar is set pretty low, as you can purchase a tank with heater and air pump for $72 from Kinsten, which is able to hold larger boards than mine - but that's not the point of the exercise, innit?

The basis for this will be an extruded plastic photo frame I found at the Reject Shop. Here's what it looks like:
Front - all glass except for the thin plastic edge

Back - the extruded plastic.
So the plan is to cut the short edge with the hanger off, cut webs out of the back, then silicone the front glass in from the back. Then, a second pane of glass will be siliconed onto the back. The thickness of the extrusion means there will be 11mm between the front glass and the back glass. Perfect. The internal dimensions will be 120mm x 170mm, but there will be that round hanger from the side poking out into that. I may cut and seal that off. That will complete the basic tank (some kind of "feet" will need to be siliconed on, I think). Total maximum volume will be about 230ml. I'm going to orient it "portrait" so that less etchant will be required to etch small boards - that is, you can half fill it.


I've ordered a small aquarium air pump, tubing and an "air-curtain" (aka, length of 10mm rubber hose with small perforations along it's length) from various Hong-Kong ebay retailers. This will be placed at the base of the tank.


Plan is to use a string of resistors encased in heatshrink tubing, placed at the bottom of the tank, above the air curtain. I haven't yet purchased these. It's suggested to keep the etchant solution at 55-60 degrees celsius, so I'll do a bit of calculation soon to see how much power is really required.

Total cost so far

2"FORMAT" 6x8" photo frames$6.00
1Small tube of silicone sealant$8.50
1Aquarium air pump (incl delivery)$6.58
12 metre length of air tubing (incl delivery)$2.45
130cm air curtain (incl delivery)$1.96
Total so far:     $25.49

Saturday, 31 December 2011

Creating PCBs addendum - drilling

Just a quick one to finish up the Creating PCBs series. I've loaded the demo PCB into the CNC machine and set it up to drill the header holes.
Here's the final result:
The area on the right is where I attempted to tin some tracks with solder. I need some new solder wick I think, and some liquid flux.

Some stats on how the drilling was done:
1mm HSS drill bit in a standard mains power drill, mounted in my homemade CNC machine. The power drill nameplate says 2700 rpm max speed. I had it set to max, so the "spindle speed" was somewhere near that.
CNC driven by EMC2 from a IBM Thinkpad G40
G-code generated by pcb-gcode user-language program in Eagle 5.11
Feed speed: 90mm/min.
Drill depth: 2mm
Retract height: 1mm
Dwell: 0.1 seconds

I had to add these commands to the generated gcode output to get it to work correctly:
F90 (set feed rate 90mm/min)
Z-2 R1 P0.1 (set Z depth, retract and dwell, added to first drill line only. Values still apply on subsequent drill movements)

And of course, here's a video of the CNC in action...

Tuesday, 15 November 2011

Creating PCBs - Etching and Lessons Learnt

Next step, after exposing the photo-resist and developing the un-exposed areas away is to etch away the copper where is has been exposed.
This was done in a solution of ammonium persulphate - it's my first time using this, as in the past I'd always used ferric chloride. It's nice that the ammonium solution is clear, as it makes it easier to see the process occurring.
Something I didn't expect is the requirement for some gentle heating of the ammonium solution for the etching to occur. With ferric chloride, the etching would occur at room temperature; the ammonium required me to place the etching container into a warm water bath (about 60°C) before anything appeared to happen. Agitation during the etching was performed manually with a small, soft-bristled nylon brush.

Here's the result, with the photo-resist still on the board
Copper etched, photo-resist still in place
The middle looks awful, because of what went wrong with the photo-resist. What's odd though is that there are specks of copper that don't seem to be covered by photo-resist, but haven etched away. The left and right areas look acceptable. The right has lost some of the numerals, but that was due to under-exposure at the photo-resist step. Wherever the photo-resist was, the copper has stayed, so that speaks well for the stability of that layer in the ammonium solution.

The next shot is with the photo-resist removed. This can be removed by abrasion, but I chose to use a caustic solution to remove it. I used a cheap oven cleaner product. A small amount sprayed on the board, and the photo-resist just brushed away.
Photo-resist removed
This shows how badly the center section has gone. The right side looks good - the tracks, at least. The left side SSOP pads look a bit "fat" in the top right. The bottom left looks "dirty" between the pads

Etched board - back-lit 
The back-lit shot reveals the true result. The left side does have unwanted bridges between the pins of the SSOP package, and the vertical lines aren't as clean as the centre and right, either.

Lessons Learnt
Overall, I'd say this wasn't a bad result for a first attempt - OK, so the result wouldn't have been usable if it were a real board, but I think that it was a valuable exercise as there are some things to take away from it for next time:

  1. Application of the photo-resist film needs more care.
    I think I rushed this, and there was wrinkling near the centre that has caused that part of the etching to fail. I was also concerned about the light sensitivity of the film, and rushed it. It's not that sensitive.
    Consider buying pre-sensitised board in future.
  2. Artwork sandwich needs more pressure
    There are some areas of the board that look like they aren't as sharp as others. Next time I'll add a piece of 3mm polystyrene foam to the back of the artwork stack to ensure the pressure is sufficient and uniform.
  3. Create artwork in reverse
    The artwork was used printed side UP, which meant that there was the possibility of light bleeding through the thickness of the transparency sheet. The artwork should have been printed in reverse image, and used printed side DOWN.
  4. Best exposure time seems to be around 2:30. More time seems less problematic than shorter, particularly where fine details are involved, but may be causing "fattening" of the traces. This may be alleviated by using reversed artwork (above)
  5. Closer inspection required at the developer stage
    Closer inspection of the board after the photo-resist developing stage may have indicated that some resist had not etched away. Another short dip in the developer may have resolved some of the final blemishes. Need to investigate how critical the development time is and whether more time will damage the exposed resist or not.

Sunday, 6 November 2011

Creating PCBs - Exposing the board

Now it's time to expose the photosensitive film to the UV light through the negative artwork mask. To get a clear image it's important that the artwork be held tightly against the board.
For this, I've used a cheap $2 plastic photo frame that I've cut down the length to fit neatly into the UV lamp. In this is (from the top)

  1. Glass (which I broke the corner off, cutting it down to fit the re-sized photo frame. OK, I suck at cutting glass)
  2. 1 sheet of rapidraw film, just to diffuse the UV light a little
  3. The artwork
  4. The copper board with photosensitive film
  5. A sheet of A4 paper, folded, to give the sandwich some more thickness
  6. The cut-down original backing plate of the photo frame.
It looks like this.

So this assembly goes into the UV lamp, like so:
And is exposed.

Exposure timing
I'd previously done an exposure timing test with the film, but not with the film on copper board. The exposure test is done by progressively covering sections of the film, and determining which section has been exposed sufficiently where the artwork is clear, but not exposed where the artwork is dark.
Too little exposure, and the film won't harden enough (with negative film, the exposed areas of film harden)
Too much, and the areas that shouldn't have been exposed may start to harden. This is why the artwork contrast is very important.
OK, so prior experimentation indicated that about 2 minutes should be enough. With this test board, I had three identical patterns, so I exposed one section for 2 minutes, the next for 2:30, and the last for 3 minutes.

This is the result:
From left to right, 3 min, 2.5 min and 2 min exposure
The vendor says that the film will darken where it is exposed, and you can see that is the case. In fact, at this point, it all looks quite good. Now to remove the un-exposed areas with the developing solution.
3 minutes on left, 2 minutes on right
Hmm, this shows some problems. The rightmost numerals have etched away in some cases. I'm not sure if it's due to underexposure, or if the film was not bonded sufficiently with the copper. The center top, I don't know WTF happened there - the only explanation I can come up with was that the artwork wasn't pressed well enough against the film, and some light has spilled? I would have expected the actual artwork to be blurry if that were the case, however. The leftmost exposure looks good.
The actual development of the film occurs pretty quickly (it's more of a "stripping" of the un-exposed regions), and I'm not sure yet what occurs if the film is over developed.

Next time, we'll see what the copper etching reveals...