In this short post, I'd like to describe how to leverage Apache APISIX in containers, drawing on personal experiences with Spring Boot and WebSphere administration.
Though I always worked on the Dev side of IT, I was also interested in the Ops side. I even had a short experience being a WebSphere admin: I used it several times, helping Ops deal with the Admin console while being a developer.
Providing a single package that Ops can configure and deploy in different environments is very important. As a JVM developer, I've been happy using Spring Boot and its wealth of configuration options: command-line parameters, JVM parameters, files, profiles, environment variables, etc.
File-based configuration
The foundation of configuring Apache APISIX is file-based. The default values are found in the /usr/local/apisix/conf/apisix/config-default.yaml configuration file. For example, by default, Apache APISIX runs on port 9080, and the admin port is 9180. That's because of the default configuration:
apisix:
  node_listen:
    - 9080           #1
#...
deployment:
  admin:
    admin_listen:
      ip: 0.0.0.0
      port: 9180     #2
- Regular port
- Admin port
To override values, we need to provide a file named config.yaml in the /usr/local/apisix/conf/apisix directory:
apisix:
  node_listen:
    - 9090           #1
deployment:
  admin:
    admin_listen:
      port: 9190     #1
- Override values
Now, Apache APISIX should run on port 9090, and the admin port should be 9190. Here's how to run the Apache APISIX container with the above configuration:
docker run -it --rm apache/apisix:3.4.1-debian \
                 -p 9090:9090 -p 9190:9190 \
                 -v ./config.yaml:/usr/local/apisix/conf/apisix/config.yaml
Environment-based configuration
The downside of a pure file-based configuration is that you must provide a dedicated file for each environment, even if only a single parameter changes. Apache APISIX allows replacement via environment variables in the configuration file to account for that.
apisix:
  node_listen:
    - ${{APISIX_NODE_LISTEN:=}}                  #1
deployment:
  admin:
    admin_listen:
      port: ${{DEPLOYMENT_ADMIN_ADMIN_LISTEN:=}} #1
- Replace the placeholder with its environment variable value at runtime
We can reuse the same file in every environment and hydrate it with the context-dependent environment variables:
docker run -it --rm apache/apisix:3.4.1-debian \
                 -e APISIX_NODE_LISTEN=9090 \
                 -e DEPLOYMENT_ADMIN_ADMIN_LISTEN=9190 \
                 -p 9090:9090 -p 9190:9190 \
                 -v ./config.yaml:/usr/local/apisix/conf/apisix/config.yaml
Icing on the cake, we can also offer a default value:
apisix:
  node_listen:
    - ${{APISIX_NODE_LISTEN:=9080}}                  #1
deployment:
  admin:
    admin_listen:
      port: ${{DEPLOYMENT_ADMIN_ADMIN_LISTEN:=9180}} #1
- If no environment variable is provided, use those ports; otherwise, use the environment variables' value
The trick works in standalone mode with the apisix. yaml file. You can parameterize every context-dependent variable and secrets with it:
routes:
  - uri: /*
    upstream:
      nodes:
        "httpbin:80": 1
    plugins:
      openid-connect:
        client_id: apisix
        client_secret: ${{OIDC_SECRET}}
        discovery: https://${{OIDC_ISSUER}}/.well-known/openid-configuration
        redirect_uri: http://localhost:9080/callback
        scope: openid
        session:
          secret: ${{SESSION_SECRET}}
Conclusion
When configuring Apache APISIX, we should ensure it's as operable as possible. In this post, I've described several ways to make it so.
Happy Apache APISIX!
To go further: